26#ifndef OOMPH_TRIANGLE_MESH_TEMPLATE_CC
27#define OOMPH_TRIANGLE_MESH_TEMPLATE_CC
32#include "../generic/map_matrix.h"
33#include "../generic/multi_domain.h"
34#include "../generic/projection.h"
35#include "../generic/face_element_as_geometric_object.h"
43 template<
class ELEMENT>
45 const bool& use_attributes)
48 MeshChecker::assert_geometric_element<TElementGeometricBase, ELEMENT>(2);
51 unsigned nelem = Tmp_mesh_pt->nelement();
52 Element_pt.resize(nelem);
55 unsigned nnode_scaffold = Tmp_mesh_pt->nnode();
59 std::map<Node*, unsigned> old_global_number;
62 for (
unsigned inod = 0; inod < nnode_scaffold; inod++)
64 Node* old_node_pt = Tmp_mesh_pt->node_pt(inod);
65 old_global_number[old_node_pt] = inod;
69 Oomph_vertex_nodes_id.resize(nnode_scaffold);
72 Node_pt.resize(nnode_scaffold, 0);
75 unsigned nbound = Tmp_mesh_pt->nboundary();
78 set_nboundary(nbound);
79 Boundary_element_pt.resize(nbound);
80 Face_index_at_boundary.resize(nbound);
86 Boundary_region_element_pt.resize(nbound);
87 Face_index_region_at_boundary.resize(nbound);
91 for (
unsigned e = 0;
e < nelem;
e++)
93 Element_pt[
e] =
new ELEMENT;
97 unsigned nnod_el = Tmp_mesh_pt->finite_element_pt(0)->nnode();
102 std::map<Node*, unsigned> global_number;
103 unsigned global_count = 0;
106 std::map<double, Vector<FiniteElement*>> element_attribute_map;
113 element_attribute_map[0].resize(0);
117 for (
unsigned e = 0;
e < nelem;
e++)
120 for (
unsigned j = 0; j < nnod_el; j++)
123 Node* scaffold_node_pt = Tmp_mesh_pt->finite_element_pt(
e)->node_pt(j);
127 unsigned j_global = global_number[scaffold_node_pt];
133 Oomph_vertex_nodes_id[global_count] =
134 old_global_number[scaffold_node_pt];
138 std::set<unsigned>* boundaries_pt;
139 scaffold_node_pt->get_boundaries_pt(boundaries_pt);
142 Node* new_node_pt = 0;
145 if (boundaries_pt != 0)
149 finite_element_pt(
e)->construct_boundary_node(j, time_stepper_pt);
152 for (std::set<unsigned>::iterator it = boundaries_pt->begin();
153 it != boundaries_pt->end();
156 add_boundary_node(*it, new_node_pt);
164 finite_element_pt(
e)->construct_node(j, time_stepper_pt);
171 global_number[scaffold_node_pt] = global_count;
177 Node_pt[global_count - 1] = new_node_pt;
180 for (
unsigned i = 0;
i < finite_element_pt(
e)->dim();
i++)
182 new_node_pt->x(
i) = scaffold_node_pt->x(
i);
188 finite_element_pt(
e)->node_pt(j) = Node_pt[j_global - 1];
195 element_attribute_map[Tmp_mesh_pt->element_attribute(
e)].push_back(
196 finite_element_pt(
e));
204 unsigned n_attribute = element_attribute_map.size();
207 this->Region_attribute.resize(n_attribute);
212 element_attribute_map.begin();
213 it != element_attribute_map.end();
216 this->Region_attribute[count] = it->first;
217 Region_element_pt[
static_cast<unsigned>(Region_attribute[count])] =
227 unsigned boundary_id = 0;
231 unsigned n_node_1d = finite_element_pt(0)->nnode_1d();
232 unsigned dim = finite_element_pt(0)->dim();
238 unsigned n_node = finite_element_pt(0)->nnode();
241 unsigned n_global_edge = Tmp_mesh_pt->nglobal_edge();
245 for (
unsigned e = 0;
e < nelem;
e++)
249 FiniteElement*
const tmp_elem_pt = Tmp_mesh_pt->finite_element_pt(
e);
252 unsigned n_edge_node = 3 * (n_node_1d - 1);
256 for (
unsigned n = n_edge_node; n < n_node; ++n)
266 for (
unsigned i = 0;
i < dim;
i++)
272 Node_pt.push_back(new_node_pt);
280 for (
unsigned j = 0; j < 3; j++)
283 boundary_id = Tmp_mesh_pt->edge_boundary(
e, j);
286 unsigned edge_index = Tmp_mesh_pt->edge_index(
e, j);
289 if (nodes_on_global_edge[edge_index].size() == 0)
292 for (
unsigned j2 = 0; j2 < n_node_1d - 2; ++j2)
295 Node* new_node_pt = 0;
303 this->add_boundary_node(boundary_id - 1, new_node_pt);
316 for (
unsigned i = 0;
i < dim;
i++)
322 Node_pt.push_back(new_node_pt);
325 nodes_on_global_edge[edge_index].push_back(new_node_pt);
337 for (
unsigned j2 = 0; j2 < n_node_1d - 2; ++j2)
342 nodes_on_global_edge[edge_index][n_node_1d - 3 - j2];
351 Boundary_element_pt[boundary_id - 1].push_back(elem_pt);
354 Face_index_at_boundary[boundary_id - 1].push_back((j + 2) % 3);
359 unsigned tmp_region =
360 static_cast<unsigned>(Tmp_mesh_pt->element_attribute(
e));
362 Boundary_region_element_pt[boundary_id - 1][tmp_region].push_back(
366 Face_index_region_at_boundary[boundary_id - 1][tmp_region]
367 .push_back((j + 2) % 3);
376 Lookup_for_elements_next_boundary_is_setup =
true;
386 template<
class ELEMENT>
403 unsigned n_repeated_ele = 0;
405 const unsigned n_regions = this->nregion();
409 std::map<FiniteElement*, FiniteElement*> face_to_bulk_element_pt;
418 for (
unsigned rr = 0; rr < n_regions; rr++)
420 const unsigned region_id =
421 static_cast<unsigned>(this->Region_attribute[rr]);
424 const unsigned nel_in_region =
425 this->nboundary_element_in_region(b, region_id);
427 unsigned nel_repetead_in_region = 0;
431 if (nel_in_region > 0)
435 bool repeated =
false;
438 for (
unsigned e = 0;
e < nel_in_region;
e++)
442 this->boundary_element_in_region_pt(b, region_id,
e);
446 if (this->is_mesh_distributed() && bulk_elem_pt->
is_halo())
457 this->face_index_at_boundary_in_region(b, region_id,
e);
465 const unsigned n_nodes = tmp_ele_pt->
nnode();
467 std::pair<Node*, Node*> tmp_pair = std::make_pair(
470 std::pair<Node*, Node*> tmp_pair_inverse = std::make_pair(
474 const unsigned n_done_nodes = done_nodes_pt.size();
475 for (
unsigned l = 0; l < n_done_nodes; l++)
477 if (tmp_pair == done_nodes_pt[l] ||
478 tmp_pair_inverse == done_nodes_pt[l])
480 nel_repetead_in_region++;
490 done_nodes_pt.push_back(tmp_pair);
492 face_el_pt.push_back(tmp_ele_pt);
494 face_to_bulk_element_pt[tmp_ele_pt] = bulk_elem_pt;
508 nele += nel_in_region;
510 n_repeated_ele += nel_repetead_in_region;
519 nele = this->nboundary_element(b);
526 bool repeated =
false;
529 for (
unsigned e = 0;
e < nele;
e++)
536 if (this->is_mesh_distributed() && bulk_elem_pt->
is_halo())
546 int face_index = this->face_index_at_boundary(b,
e);
554 const unsigned n_nodes = tmp_ele_pt->
nnode();
556 std::pair<Node*, Node*> tmp_pair = std::make_pair(
559 std::pair<Node*, Node*> tmp_pair_inverse = std::make_pair(
563 const unsigned n_done_nodes = done_nodes_pt.size();
564 for (
unsigned l = 0; l < n_done_nodes; l++)
566 if (tmp_pair == done_nodes_pt[l] ||
567 tmp_pair_inverse == done_nodes_pt[l])
581 done_nodes_pt.push_back(tmp_pair);
583 face_el_pt.push_back(tmp_ele_pt);
585 face_to_bulk_element_pt[tmp_ele_pt] = bulk_elem_pt;
603 nele -= n_repeated_ele;
606 if (nele != face_el_pt.size())
608 std::ostringstream error_message;
610 <<
"The independent counting of face elements (" << nele <<
") for "
611 <<
"boundary (" << b <<
") is different\n"
612 <<
"from the real number of face elements in the container ("
613 << face_el_pt.size() <<
")\n";
615 "TriangleMesh::identify_boundary_segments_and_assign_"
616 "initial_zeta_values()",
617 OOMPH_EXCEPTION_LOCATION);
630 std::vector<bool> is_halo_face_element(nele,
false);
633 unsigned nnon_halo_face_elements = 0;
636 for (
unsigned ie = 0; ie < nele; ie++)
641 FiniteElement* tmp_bulk_ele_pt = face_to_bulk_element_pt[face_ele_pt];
643 if (!tmp_bulk_ele_pt->
is_halo())
645 is_halo_face_element[ie] =
false;
646 nnon_halo_face_elements++;
651 is_halo_face_element[ie] =
true;
657 const unsigned nhalo_face_element = nele - nnon_halo_face_elements;
658 if (nhalo_face_element > 0)
660 std::ostringstream error_message;
662 <<
"There should not be halo face elements since they were not "
663 <<
"considered when computing the face elements\n\n"
664 <<
"The number of found halo face elements is: " << nhalo_face_element
667 "TriangleMesh::identify_boundary_segments_and_assign_"
668 "initial_zeta_values()",
669 OOMPH_EXCEPTION_LOCATION);
679 unsigned nsorted_face_elements = 0;
683 std::map<FiniteElement*, bool> done_el;
687 std::map<FiniteElement*, bool> is_inverted;
690 while (nsorted_face_elements < nnon_halo_face_elements)
694 std::list<FiniteElement*> sorted_el_pt;
695 sorted_el_pt.clear();
699 bool found_initial_face_element =
false;
705 for (iface = 0; iface < nele; iface++)
707 if (!is_halo_face_element[iface])
709 ele_face_pt = face_el_pt[iface];
711 if (!done_el[ele_face_pt])
714 found_initial_face_element =
true;
716 nsorted_face_elements++;
718 sorted_el_pt.push_back(ele_face_pt);
720 done_el[ele_face_pt] =
true;
727 if (!found_initial_face_element)
729 std::ostringstream error_message;
731 <<
"Could not find an initial face element for the current segment\n";
733 "TriangleMesh::identify_boundary_segments_and_"
734 "assign_initial_zeta_values()",
735 OOMPH_EXCEPTION_LOCATION);
740 const unsigned nnod = ele_face_pt->
nnode();
744 Node* left_node_pt = ele_face_pt->
node_pt(0);
745 Node* right_node_pt = ele_face_pt->
node_pt(nnod - 1);
749 bool face_element_added =
false;
758 for (
unsigned iiface = iface; iiface < nele; iiface++)
761 face_element_added =
false;
764 ele_face_pt = face_el_pt[iiface];
768 if (!(done_el[ele_face_pt] || is_halo_face_element[iiface]))
771 Node* local_left_node_pt = ele_face_pt->
node_pt(0);
772 Node* local_right_node_pt = ele_face_pt->
node_pt(nnod - 1);
774 if (left_node_pt == local_right_node_pt)
776 left_node_pt = local_left_node_pt;
777 sorted_el_pt.push_front(ele_face_pt);
778 is_inverted[ele_face_pt] =
false;
779 face_element_added =
true;
782 else if (left_node_pt == local_left_node_pt)
784 left_node_pt = local_right_node_pt;
785 sorted_el_pt.push_front(ele_face_pt);
786 is_inverted[ele_face_pt] =
true;
787 face_element_added =
true;
790 else if (right_node_pt == local_left_node_pt)
792 right_node_pt = local_right_node_pt;
793 sorted_el_pt.push_back(ele_face_pt);
794 is_inverted[ele_face_pt] =
false;
795 face_element_added =
true;
798 else if (right_node_pt == local_right_node_pt)
800 right_node_pt = local_left_node_pt;
801 sorted_el_pt.push_back(ele_face_pt);
802 is_inverted[ele_face_pt] =
true;
803 face_element_added =
true;
806 if (face_element_added)
808 done_el[ele_face_pt] =
true;
809 nsorted_face_elements++;
815 }
while (face_element_added &&
816 (nsorted_face_elements < nnon_halo_face_elements));
819 segment_sorted_ele_pt.push_back(sorted_el_pt);
824 const unsigned nsegments = segment_sorted_ele_pt.size();
855 if (nnon_halo_face_elements > 0 && nsegments == 0)
857 std::ostringstream error_message;
859 <<
"The number of segments is zero, but the number of nonhalo\n"
860 <<
"elements is: (" << nnon_halo_face_elements <<
")\n";
862 "TriangleMesh::identify_boundary_segments_and_assign_"
863 "initial_zeta_values()",
864 OOMPH_EXCEPTION_LOCATION);
870 for (
unsigned is = 0; is < nsegments; is++)
873 if (segment_sorted_ele_pt[is].size() == 0)
875 std::ostringstream error_message;
876 error_message <<
"The (" << is <<
")-th segment has no elements\n";
878 "TriangleMesh::identify_boundary_segments_and_"
879 "assign_initial_zeta_values()",
880 OOMPH_EXCEPTION_LOCATION);
885 FiniteElement* first_ele_pt = segment_sorted_ele_pt[is].front();
888 const unsigned nnod = first_ele_pt->
nnode();
891 Node* first_node_pt = first_ele_pt->
node_pt(0);
892 if (is_inverted[first_ele_pt])
894 first_node_pt = first_ele_pt->
node_pt(nnod - 1);
898 FiniteElement* last_ele_pt = segment_sorted_ele_pt[is].back();
901 Node* last_node_pt = last_ele_pt->
node_pt(nnod - 1);
902 if (is_inverted[last_ele_pt])
904 last_node_pt = last_ele_pt->
node_pt(0);
908 double x_left = first_node_pt->x(0);
909 double y_left = first_node_pt->x(1);
918 if (this->boundary_geom_object_pt(b) != 0)
920 first_node_pt->get_coordinates_on_boundary(b, zeta);
921 initial_zeta_segment[is] = zeta[0];
922 last_node_pt->get_coordinates_on_boundary(b, zeta);
923 final_zeta_segment[is] = zeta[0];
927 std::set<Node*> local_nodes_pt;
928 local_nodes_pt.insert(first_node_pt);
931 for (std::list<FiniteElement*>::iterator it =
932 segment_sorted_ele_pt[is].begin();
933 it != segment_sorted_ele_pt[is].end();
942 if (is_inverted[el_pt])
949 for (
unsigned j = 1; j < nnod; j++)
951 Node* nod_pt = el_pt->
node_pt(k_nod);
955 double x_right = nod_pt->x(0);
956 double y_right = nod_pt->x(1);
959 zeta[0] += sqrt((x_right - x_left) * (x_right - x_left) +
960 (y_right - y_left) * (y_right - y_left));
977 local_nodes_pt.insert(nod_pt);
983 segment_arclength[is] = zeta[0];
986 nvertices_per_segment[is] = local_nodes_pt.size();
989 segment_all_nodes_pt.push_back(local_nodes_pt);
995 if (segment_all_nodes_pt.size() != nsegments)
997 std::ostringstream error_message;
998 error_message <<
"The number of segments (" << nsegments
999 <<
") and the number of "
1000 <<
"sets of nodes (" << segment_all_nodes_pt.size()
1001 <<
") representing\n"
1002 <<
"the\nsegments is different!!!\n\n";
1004 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
1032 const unsigned nsegments_initial_coordinates =
1035 const unsigned nsegments_final_coordinates =
1038 if (nsegments_initial_coordinates != nsegments_final_coordinates)
1040 std::stringstream error_message;
1042 <<
"The number of segments that present initial coordinates "
1043 << nsegments_initial_coordinates <<
" is different from "
1044 <<
"the\nnumber of segments that present final coordinates "
1045 << nsegments_final_coordinates <<
"\n\n";
1047 OOMPH_CURRENT_FUNCTION,
1048 OOMPH_EXCEPTION_LOCATION);
1053 if (nsegments_initial_coordinates != nsegments)
1055 std::stringstream error_message;
1056 error_message <<
"Working with boundary (" << b
1057 <<
").\n The number of initial and "
1058 <<
"final coordinates (" << nsegments_initial_coordinates
1059 <<
") is different from\n"
1060 <<
"the number of found segments (" << nsegments
1063 OOMPH_CURRENT_FUNCTION,
1064 OOMPH_EXCEPTION_LOCATION);
1077 Vector<double> original_mesh_segment_initial_arclength(nsegments);
1080 for (
unsigned is = 0; is < nsegments; is++)
1082 original_mesh_segment_initial_coordinate[is].resize(2);
1083 original_mesh_segment_final_coordinate[is].resize(2);
1084 for (
unsigned k = 0; k < 2; k++)
1086 original_mesh_segment_initial_coordinate[is][k] =
1088 original_mesh_segment_final_coordinate[is][k] =
1092 if (this->boundary_geom_object_pt(b) != 0)
1094 original_mesh_segment_initial_zeta[is] =
1096 original_mesh_segment_final_zeta[is] =
1101 original_mesh_segment_initial_arclength[is] =
1103 original_mesh_segment_final_arclength[is] =
1109 Boundary_segment_inverted[b].clear();
1110 Boundary_segment_initial_coordinate[b].clear();
1111 Boundary_segment_final_coordinate[b].clear();
1113 Boundary_segment_initial_zeta[b].clear();
1114 Boundary_segment_final_zeta[b].clear();
1116 Boundary_segment_initial_arclength[b].clear();
1117 Boundary_segment_final_arclength[b].clear();
1123 std::map<unsigned, bool> segment_done;
1124 for (
unsigned is = 0; is < nsegments; is++)
1128 bool found_original_segment =
false;
1137 segment_sorted_ele_pt[is].front();
1140 const unsigned nnod = current_seg_initial_ele_pt->
nnode();
1143 Node* current_seg_first_node_pt =
1144 current_seg_initial_ele_pt->
node_pt(0);
1145 if (is_inverted[current_seg_initial_ele_pt])
1147 current_seg_first_node_pt =
1148 current_seg_initial_ele_pt->
node_pt(nnod - 1);
1153 segment_sorted_ele_pt[is].back();
1156 Node* current_seg_last_node_pt =
1157 current_seg_last_ele_pt->
node_pt(nnod - 1);
1158 if (is_inverted[current_seg_last_ele_pt])
1160 current_seg_last_node_pt = current_seg_last_ele_pt->
node_pt(0);
1164 for (
unsigned i = 0;
i < 2;
i++)
1166 current_seg_initial_coord[
i] = current_seg_first_node_pt->x(
i);
1167 current_seg_final_coord[
i] = current_seg_last_node_pt->x(
i);
1174 for (
unsigned orig_s = 0; orig_s < nsegments; orig_s++)
1176 if (!segment_done[orig_s])
1180 original_mesh_segment_initial_coordinate[orig_s];
1182 original_mesh_segment_final_coordinate[orig_s];
1187 ((current_seg_initial_coord[0] - initial_coordinate[0]) *
1188 (current_seg_initial_coord[0] - initial_coordinate[0])) +
1189 ((current_seg_initial_coord[1] - initial_coordinate[1]) *
1190 (current_seg_initial_coord[1] - initial_coordinate[1]));
1198 dist = ((current_seg_final_coord[0] - final_coordinate[0]) *
1199 (current_seg_final_coord[0] - final_coordinate[0])) +
1200 ((current_seg_final_coord[1] - final_coordinate[1]) *
1201 (current_seg_final_coord[1] - final_coordinate[1]));
1210 current_segment_to_original_segment_index[is] = orig_s;
1213 Boundary_segment_inverted[b].push_back(0);
1216 Boundary_segment_initial_coordinate[b].push_back(
1217 initial_coordinate);
1218 Boundary_segment_final_coordinate[b].push_back(
1222 if (this->boundary_geom_object_pt(b) != 0)
1225 Boundary_segment_initial_zeta[b].push_back(
1226 original_mesh_segment_initial_zeta[orig_s]);
1227 Boundary_segment_final_zeta[b].push_back(
1228 original_mesh_segment_final_zeta[orig_s]);
1234 Boundary_segment_initial_arclength[b].push_back(
1235 original_mesh_segment_initial_arclength[orig_s]);
1236 Boundary_segment_final_arclength[b].push_back(
1237 original_mesh_segment_final_arclength[orig_s]);
1240 segment_done[orig_s] =
true;
1242 found_original_segment =
true;
1254 ((current_seg_initial_coord[0] - final_coordinate[0]) *
1255 (current_seg_initial_coord[0] - final_coordinate[0])) +
1256 ((current_seg_initial_coord[1] - final_coordinate[1]) *
1257 (current_seg_initial_coord[1] - final_coordinate[1]));
1258 dist_inv = sqrt(dist_inv);
1268 ((current_seg_final_coord[0] - initial_coordinate[0]) *
1269 (current_seg_final_coord[0] - initial_coordinate[0])) +
1270 ((current_seg_final_coord[1] - initial_coordinate[1]) *
1271 (current_seg_final_coord[1] - initial_coordinate[1]));
1272 dist_inv = sqrt(dist_inv);
1281 current_segment_to_original_segment_index[is] = orig_s;
1284 Boundary_segment_inverted[b].push_back(1);
1287 Boundary_segment_initial_coordinate[b].push_back(
1288 initial_coordinate);
1289 Boundary_segment_final_coordinate[b].push_back(
1293 if (this->boundary_geom_object_pt(b) != 0)
1296 Boundary_segment_initial_zeta[b].push_back(
1297 original_mesh_segment_initial_zeta[orig_s]);
1298 Boundary_segment_final_zeta[b].push_back(
1299 original_mesh_segment_final_zeta[orig_s]);
1304 Boundary_segment_initial_arclength[b].push_back(
1305 original_mesh_segment_initial_arclength[orig_s]);
1306 Boundary_segment_final_arclength[b].push_back(
1307 original_mesh_segment_final_arclength[orig_s]);
1310 segment_done[orig_s] =
true;
1312 found_original_segment =
true;
1327 if (!found_original_segment)
1329 std::stringstream error_message;
1331 <<
"The (" << is <<
")-th segment on the current segment was not\n"
1332 <<
"found when trying to identify it with the original mesh's\n"
1333 <<
"segment coordinates\n";
1335 OOMPH_CURRENT_FUNCTION,
1336 OOMPH_EXCEPTION_LOCATION);
1357 if (
this != original_mesh_pt)
1370 const double boundary_arclength =
1371 std::max(first_node_zeta_coordinate[0], last_node_zeta_coordinate[0]);
1373 for (
unsigned is = 0; is < nsegments; is++)
1378 if (boundary_geom_object_pt(b) == 0)
1395 FiniteElement* first_ele_pt = segment_sorted_ele_pt[is].front();
1398 const unsigned nnod = first_ele_pt->
nnode();
1401 Node* first_node_pt = first_ele_pt->
node_pt(0);
1402 if (is_inverted[first_ele_pt])
1404 first_node_pt = first_ele_pt->
node_pt(nnod - 1);
1408 FiniteElement* last_ele_pt = segment_sorted_ele_pt[is].back();
1411 Node* last_node_pt = last_ele_pt->
node_pt(nnod - 1);
1412 if (is_inverted[last_ele_pt])
1414 last_node_pt = last_ele_pt->
node_pt(0);
1421 if (!Boundary_segment_inverted[b][is])
1423 first_node_pt->get_coordinates_on_boundary(
1424 b, current_segment_initial_arclen);
1425 last_node_pt->get_coordinates_on_boundary(
1426 b, current_segment_final_arclen);
1430 first_node_pt->get_coordinates_on_boundary(
1431 b, current_segment_final_arclen);
1432 last_node_pt->get_coordinates_on_boundary(
1433 b, current_segment_initial_arclen);
1441 bool increasing_order =
false;
1445 if (current_segment_initial_arclen[0] <
1446 current_segment_final_arclen[0])
1448 increasing_order =
true;
1452 else if (current_segment_initial_arclen[0] >
1453 current_segment_final_arclen[0])
1455 increasing_order =
false;
1460 std::stringstream error_message;
1462 <<
"It was not possible to identify if the zeta values on "
1463 <<
"boundary (" << b <<
")\nand segment (" << is
1464 <<
") should go in "
1465 <<
"increasing or decreasing order.\n--- New mesh ---\n"
1466 <<
"Current segment initial arclength: ("
1467 << current_segment_initial_arclen[0] <<
")\n"
1468 <<
"First node coordinates: (" << first_node_pt->x(0) <<
", "
1469 << first_node_pt->x(1) <<
")\n"
1470 <<
"Current segment final arclength: ("
1471 << current_segment_final_arclen[0] <<
")\n"
1472 <<
"Last node coordinates: (" << last_node_pt->x(0) <<
", "
1473 << last_node_pt->x(1) <<
")\n"
1474 <<
"Current segment arclength: (" << segment_arclength[is]
1477 OOMPH_CURRENT_FUNCTION,
1478 OOMPH_EXCEPTION_LOCATION);
1484 const unsigned prev_s = current_segment_to_original_segment_index[is];
1485 const double original_segment_initial_arclength =
1487 const double original_segment_final_arclength =
1492 bool original_increasing_order =
false;
1497 double starting_arclength = 0.0;
1498 if (original_segment_final_arclength >
1499 original_segment_initial_arclength)
1502 original_increasing_order =
true;
1504 starting_arclength = original_segment_initial_arclength;
1506 else if (original_segment_final_arclength <
1507 original_segment_initial_arclength)
1510 original_increasing_order =
false;
1512 starting_arclength = original_segment_final_arclength;
1517 std::stringstream error_message;
1519 <<
"It was not possible to identify if the zeta values on "
1520 <<
"boundary (" << b <<
")\nand segment (" << is
1521 <<
") should go in "
1522 <<
"increasing or decreasing order.\n--- Original mesh ---\n"
1523 <<
"Original segment initial arclength: ("
1524 << original_segment_initial_arclength <<
")\n"
1525 <<
"Original segment final arclength: ("
1526 << original_segment_final_arclength <<
")\n";
1528 OOMPH_CURRENT_FUNCTION,
1529 OOMPH_EXCEPTION_LOCATION);
1536 if (increasing_order && original_increasing_order)
1552 std::set<Node*> seg_nodes_pt = segment_all_nodes_pt[is];
1555 for (std::set<Node*>::iterator it = seg_nodes_pt.begin();
1556 it != seg_nodes_pt.end();
1562 Node* nod_pt = (*it);
1564 nod_pt->get_coordinates_on_boundary(b, zeta);
1567 starting_arclength + (zeta[0] * segment_arclength[is]);
1569 zeta[0] = temp / boundary_arclength;
1571 if (std::fabs(zeta[0] - 1.0) < 1.0e-14)
1575 else if (std::fabs(zeta[0]) < 1.0e-14)
1581 nod_pt->set_coordinates_on_boundary(b, zeta);
1584 else if (!increasing_order && original_increasing_order)
1600 std::set<Node*> seg_nodes_pt = segment_all_nodes_pt[is];
1603 for (std::set<Node*>::iterator it = seg_nodes_pt.begin();
1604 it != seg_nodes_pt.end();
1610 Node* nod_pt = (*it);
1612 nod_pt->get_coordinates_on_boundary(b, zeta);
1615 starting_arclength + ((1.0 - zeta[0]) * segment_arclength[is]);
1617 zeta[0] = temp / boundary_arclength;
1619 if (std::fabs(zeta[0] - 1.0) < 1.0e-14)
1623 else if (std::fabs(zeta[0]) < 1.0e-14)
1628 nod_pt->set_coordinates_on_boundary(b, zeta);
1631 else if (increasing_order && !original_increasing_order)
1647 std::set<Node*> seg_nodes_pt = segment_all_nodes_pt[is];
1650 for (std::set<Node*>::iterator it = seg_nodes_pt.begin();
1651 it != seg_nodes_pt.end();
1657 Node* nod_pt = (*it);
1659 nod_pt->get_coordinates_on_boundary(b, zeta);
1662 starting_arclength + ((1.0 - zeta[0]) * segment_arclength[is]);
1664 zeta[0] = temp / boundary_arclength;
1666 if (std::fabs(zeta[0] - 1.0) < 1.0e-14)
1670 else if (std::fabs(zeta[0]) < 1.0e-14)
1675 nod_pt->set_coordinates_on_boundary(b, zeta);
1678 else if (!increasing_order && !original_increasing_order)
1694 std::set<Node*> seg_nodes_pt = segment_all_nodes_pt[is];
1697 for (std::set<Node*>::iterator it = seg_nodes_pt.begin();
1698 it != seg_nodes_pt.end();
1704 Node* nod_pt = (*it);
1706 nod_pt->get_coordinates_on_boundary(b, zeta);
1709 starting_arclength + (zeta[0] * segment_arclength[is]);
1711 zeta[0] = temp / boundary_arclength;
1713 if (std::fabs(zeta[0] - 1.0) < 1.0e-14)
1717 else if (std::fabs(zeta[0]) < 1.0e-14)
1722 nod_pt->set_coordinates_on_boundary(b, zeta);
1729 for (std::list<FiniteElement*>::iterator it_list =
1730 segment_sorted_ele_pt[is].begin();
1731 it_list != segment_sorted_ele_pt[is].end();
1735 const unsigned nnod = (*it_list)->nnode();
1738 Node* first_node_pt = (*it_list)->node_pt(0);
1739 if (is_inverted[(*it_list)])
1741 first_node_pt = (*it_list)->node_pt(nnod - 1);
1745 Node* last_node_pt = (*it_list)->node_pt(nnod - 1);
1746 if (is_inverted[(*it_list)])
1748 last_node_pt = (*it_list)->node_pt(0);
1753 first_node_pt->get_coordinates_on_boundary(b, zeta);
1754 if (zeta[0] < 0.0 || zeta[0] > 1.0)
1756 std::ostringstream error_message;
1758 <<
"The boundary coordinate of the first node on boundary ("
1759 << b <<
")\nand segment (" << is <<
") is out of the "
1760 <<
"allowed values [0,1]\n"
1761 <<
"The node boundary coordinate: (" << zeta[0] <<
")\n"
1762 <<
"The vertex coordinates are: (" << first_node_pt->x(0)
1763 <<
", " << first_node_pt->x(1) <<
")\n";
1765 OOMPH_CURRENT_FUNCTION,
1766 OOMPH_EXCEPTION_LOCATION);
1770 last_node_pt->get_coordinates_on_boundary(b, zeta);
1771 if (zeta[0] < 0.0 || zeta[0] > 1.0)
1773 std::ostringstream error_message;
1775 <<
"The boundary coordinate of the last node on boundary (" << b
1776 <<
")\nand segment (" << is <<
") is out of the "
1777 <<
"allowed values [0,1]\n"
1778 <<
"The node boundary coordinate: (" << zeta[0] <<
")\n"
1779 <<
"The vertex coordinates are: (" << last_node_pt->x(0) <<
", "
1780 << last_node_pt->x(1) <<
")\n";
1782 OOMPH_CURRENT_FUNCTION,
1783 OOMPH_EXCEPTION_LOCATION);
1802 Boundary_initial_coordinate[b] =
1805 Boundary_final_coordinate[b] =
1810 Boundary_initial_zeta_coordinate[b] =
1813 Boundary_final_zeta_coordinate[b] =
1820 Assigned_segments_initial_zeta_values[b] =
true;
1823 for (
unsigned i = 0;
i < nele;
i++)
1825 delete face_el_pt[
i];
1836 template<
class ELEMENT>
1849 const unsigned nproc = comm_pt->nproc();
1851 const unsigned my_rank = comm_pt->my_rank();
1859 bool is_internal_boundary =
false;
1863 std::map<FiniteElement*, FiniteElement*> face_to_bulk_element_pt;
1867 select_boundary_face_elements(
1868 all_face_ele_pt, b, is_internal_boundary, face_to_bulk_element_pt);
1871 const unsigned n_all_face_ele = all_face_ele_pt.size();
1879 std::vector<bool> is_halo_face_element(n_all_face_ele,
false);
1882 unsigned nnon_halo_face_elements = 0;
1886 for (
unsigned ie = 0; ie < n_all_face_ele; ie++)
1890 FiniteElement* tmp_bulk_ele_pt = face_to_bulk_element_pt[face_ele_pt];
1892 if (!tmp_bulk_ele_pt->
is_halo())
1895 is_halo_face_element[ie] =
false;
1897 nnon_halo_face_elements++;
1902 is_halo_face_element[ie] =
true;
1908 const unsigned nhalo_face_element =
1909 n_all_face_ele - nnon_halo_face_elements;
1917 unsigned nsorted_face_elements = 0;
1921 std::map<FiniteElement*, bool> done_el;
1925 std::map<FiniteElement*, bool> is_inverted;
1928 while (nsorted_face_elements < nnon_halo_face_elements)
1932 std::list<FiniteElement*> sorted_el_pt;
1933 sorted_el_pt.clear();
1938 bool found_initial_face_element =
false;
1944 for (iface = 0; iface < n_all_face_ele; iface++)
1946 if (!is_halo_face_element[iface])
1948 ele_face_pt = all_face_ele_pt[iface];
1950 if (!done_el[ele_face_pt])
1953 found_initial_face_element =
true;
1955 nsorted_face_elements++;
1957 sorted_el_pt.push_back(ele_face_pt);
1959 done_el[ele_face_pt] =
true;
1966 if (!found_initial_face_element)
1968 std::ostringstream error_message;
1970 <<
"Could not find an initial face element for the current segment\n";
1973 OOMPH_CURRENT_FUNCTION,
1974 OOMPH_EXCEPTION_LOCATION);
1979 const unsigned nnod = ele_face_pt->
nnode();
1983 Node* left_node_pt = ele_face_pt->
node_pt(0);
1984 Node* right_node_pt = ele_face_pt->
node_pt(nnod - 1);
1988 bool face_element_added =
false;
1997 for (
unsigned iiface = iface; iiface < n_all_face_ele; iiface++)
2000 face_element_added =
false;
2003 ele_face_pt = all_face_ele_pt[iiface];
2007 if (!(done_el[ele_face_pt] || is_halo_face_element[iiface]))
2010 Node* local_left_node_pt = ele_face_pt->
node_pt(0);
2011 Node* local_right_node_pt = ele_face_pt->
node_pt(nnod - 1);
2014 if (left_node_pt == local_right_node_pt)
2016 left_node_pt = local_left_node_pt;
2017 sorted_el_pt.push_front(ele_face_pt);
2018 is_inverted[ele_face_pt] =
false;
2019 face_element_added =
true;
2022 else if (left_node_pt == local_left_node_pt)
2024 left_node_pt = local_right_node_pt;
2025 sorted_el_pt.push_front(ele_face_pt);
2026 is_inverted[ele_face_pt] =
true;
2027 face_element_added =
true;
2030 else if (right_node_pt == local_left_node_pt)
2032 right_node_pt = local_right_node_pt;
2033 sorted_el_pt.push_back(ele_face_pt);
2034 is_inverted[ele_face_pt] =
false;
2035 face_element_added =
true;
2038 else if (right_node_pt == local_right_node_pt)
2040 right_node_pt = local_left_node_pt;
2041 sorted_el_pt.push_back(ele_face_pt);
2042 is_inverted[ele_face_pt] =
true;
2043 face_element_added =
true;
2046 if (face_element_added)
2048 done_el[ele_face_pt] =
true;
2049 nsorted_face_elements++;
2055 }
while (face_element_added &&
2056 (nsorted_face_elements < nnon_halo_face_elements));
2059 segment_sorted_ele_pt.push_back(sorted_el_pt);
2076 const unsigned nsegments = segment_sorted_ele_pt.size();
2080 if (nnon_halo_face_elements > 0 && nsegments == 0)
2082 std::ostringstream error_message;
2084 <<
"The number of segments is zero, but the number of nonhalo\n"
2085 <<
"elements is: (" << nnon_halo_face_elements <<
")\n";
2087 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
2106 for (
unsigned is = 0; is < nsegments; is++)
2109 if (segment_sorted_ele_pt[is].size() == 0)
2111 std::ostringstream error_message;
2112 error_message <<
"The (" << is <<
")-th segment has no elements\n";
2114 OOMPH_CURRENT_FUNCTION,
2115 OOMPH_EXCEPTION_LOCATION);
2120 FiniteElement* first_ele_pt = segment_sorted_ele_pt[is].front();
2123 const unsigned nnod = first_ele_pt->
nnode();
2126 Node* first_node_pt = first_ele_pt->
node_pt(0);
2127 if (is_inverted[first_ele_pt])
2129 first_node_pt = first_ele_pt->
node_pt(nnod - 1);
2133 double x_left = first_node_pt->x(0);
2134 double y_left = first_node_pt->x(1);
2143 if (this->boundary_geom_object_pt(b) != 0)
2146 first_node_pt->get_coordinates_on_boundary(b, zeta);
2148 initial_zeta_segment[is] = zeta[0];
2151 FiniteElement* last_ele_pt = segment_sorted_ele_pt[is].back();
2154 Node* last_node_pt = last_ele_pt->
node_pt(nnod - 1);
2155 if (is_inverted[last_ele_pt])
2157 last_node_pt = last_ele_pt->
node_pt(0);
2161 last_node_pt->get_coordinates_on_boundary(b, zeta);
2163 final_zeta_segment[is] = zeta[0];
2168 std::set<Node*> local_nodes_pt;
2170 local_nodes_pt.insert(first_node_pt);
2173 for (std::list<FiniteElement*>::iterator it =
2174 segment_sorted_ele_pt[is].begin();
2175 it != segment_sorted_ele_pt[is].end();
2185 if (is_inverted[el_pt])
2192 for (
unsigned j = 1; j < nnod; j++)
2194 Node* nod_pt = el_pt->
node_pt(k_nod);
2198 double x_right = nod_pt->x(0);
2199 double y_right = nod_pt->x(1);
2202 zeta[0] += sqrt((x_right - x_left) * (x_right - x_left) +
2203 (y_right - y_left) * (y_right - y_left));
2220 local_nodes_pt.insert(nod_pt);
2229 segment_arclength[is] = zeta[0];
2234 nvertices_per_segment[is] = local_nodes_pt.size();
2237 segment_all_nodes_pt.push_back(local_nodes_pt);
2259 unsigned proc_with_initial_seg = 0;
2260 unsigned proc_with_final_seg = 0;
2264 unsigned initial_segment = 0;
2265 unsigned final_segment = 0;
2274 for (
unsigned is = 0; is < nsegments; is++)
2276 for (std::list<FiniteElement*>::iterator it_seg =
2277 segment_sorted_ele_pt[is].begin();
2278 it_seg != segment_sorted_ele_pt[is].end();
2281 segment_sorted_nonhalo_ele_pt[is].push_back((*it_seg));
2288 for (
unsigned is = 0; is < nsegments; is++)
2291 FiniteElement* first_ele_pt = segment_sorted_ele_pt[is].front();
2294 const unsigned nnod = first_ele_pt->
nnode();
2297 Node* first_node_pt = first_ele_pt->
node_pt(0);
2298 if (is_inverted[first_ele_pt])
2300 first_node_pt = first_ele_pt->
node_pt(nnod - 1);
2304 FiniteElement* last_ele_pt = segment_sorted_ele_pt[is].back();
2307 Node* last_node_pt = last_ele_pt->
node_pt(nnod - 1);
2308 if (is_inverted[last_ele_pt])
2310 last_node_pt = last_ele_pt->
node_pt(0);
2317 bool attached_left_halo =
false;
2318 bool attached_right_halo =
false;
2319 if (nhalo_face_element > 0)
2321 for (
unsigned iiface = 0; iiface < n_all_face_ele; iiface++)
2337 if (is_halo_face_element[iiface])
2340 Node* left_node_pt = halo_face_ele_pt->
node_pt(0);
2341 Node* right_node_pt = halo_face_ele_pt->
node_pt(nnod - 1);
2343 if (!attached_left_halo && (first_node_pt == right_node_pt ||
2344 first_node_pt == left_node_pt))
2347 segment_sorted_ele_pt[is].push_front(halo_face_ele_pt);
2351 attached_left_halo =
true;
2354 else if (!attached_right_halo && (last_node_pt == left_node_pt ||
2355 last_node_pt == right_node_pt))
2358 segment_sorted_ele_pt[is].push_back(halo_face_ele_pt);
2361 attached_right_halo =
true;
2365 if (attached_left_halo && attached_right_halo)
2417 for (
unsigned is = 0; is < nsegments; is++)
2420 FiniteElement* left_face_ele_pt = segment_sorted_ele_pt[is].front();
2425 face_to_bulk_element_pt[left_face_ele_pt];
2428 if (tmp_left_bulk_ele_pt->
is_halo())
2435 std::ostringstream error_message;
2437 <<
"The current bulk element (left) is marked as halo but "
2438 <<
"the processor holding\nthe non-halo counterpart is "
2441 OOMPH_CURRENT_FUNCTION,
2442 OOMPH_EXCEPTION_LOCATION);
2446 unsigned left_processor =
static_cast<unsigned>(left_proc);
2447 left_processor_plus_one[is] = left_processor + 1;
2454 this->halo_element_pt(left_processor);
2458 bool left_halo_element_found =
false;
2461 const unsigned n_halo_left = left_halo_element_pt.size();
2462 for (
unsigned lh = 0; lh < n_halo_left; lh++)
2464 if (left_element_pt == left_halo_element_pt[lh])
2466 left_halo_element[is] = lh;
2468 left_halo_element_found =
true;
2475 if (!left_halo_element_found)
2477 std::ostringstream error_message;
2479 <<
"The current bulk element (left) marked as halo was "
2480 <<
"not found in the vector of halo\nelements associated "
2481 <<
"with the (" << left_processor <<
") processor.\n\n";
2483 OOMPH_CURRENT_FUNCTION,
2484 OOMPH_EXCEPTION_LOCATION);
2490 left_face_ele_pt = segment_sorted_nonhalo_ele_pt[is].front();
2493 tmp_left_bulk_ele_pt = face_to_bulk_element_pt[left_face_ele_pt];
2497 if (tmp_left_bulk_ele_pt->
is_halo())
2499 std::ostringstream error_message;
2501 <<
"The bulk element represetation of the left-most nonhalo face\n"
2502 <<
"element of the current segment (" << is
2503 <<
") is marked as halo,\n"
2504 <<
"but the face element created from it is nonhalo\n";
2506 OOMPH_CURRENT_FUNCTION,
2507 OOMPH_EXCEPTION_LOCATION);
2513 left_element_pt = tmp_left_bulk_ele_pt;
2517 bool left_haloed_element_found =
false;
2523 this->haloed_element_pt(left_processor);
2525 const unsigned nhaloed_left = left_haloed_element_pt.size();
2526 for (
unsigned lhd = 0; lhd < nhaloed_left; lhd++)
2528 if (left_element_pt == left_haloed_element_pt[lhd])
2530 left_haloed_element[is] = lhd;
2532 left_haloed_element_found =
true;
2539 if (!left_haloed_element_found)
2541 std::ostringstream error_message;
2543 <<
"The current bulk element (left) marked as haloed was "
2544 <<
"not found in the vector of haloed\nelements associated "
2545 <<
"with processor (" << left_processor <<
").\n";
2547 OOMPH_CURRENT_FUNCTION,
2548 OOMPH_EXCEPTION_LOCATION);
2555 left_processor_plus_one[is] = 0;
2557 left_halo_element[is] = 0;
2559 left_haloed_element[is] = 0;
2563 FiniteElement* right_face_ele_pt = segment_sorted_ele_pt[is].back();
2568 face_to_bulk_element_pt[right_face_ele_pt];
2571 if (tmp_right_bulk_ele_pt->
is_halo())
2578 std::ostringstream error_message;
2580 <<
"The current bulk element (right) is marked as halo but "
2581 <<
"the processor holding\nthe non-halo counterpart is "
2584 "TriangleMesh::compute_boundary_segments_"
2585 "connectivity_and_initial_zeta_values()",
2586 OOMPH_EXCEPTION_LOCATION);
2590 unsigned right_processor =
static_cast<unsigned>(right_proc);
2591 right_processor_plus_one[is] = right_processor + 1;
2598 this->halo_element_pt(right_processor);
2602 bool right_halo_element_found =
false;
2605 const unsigned nhalo_right = right_halo_element_pt.size();
2606 for (
unsigned rh = 0; rh < nhalo_right; rh++)
2608 if (right_element_pt == right_halo_element_pt[rh])
2610 right_halo_element[is] = rh;
2612 right_halo_element_found =
true;
2618 if (!right_halo_element_found)
2620 std::ostringstream error_message;
2622 <<
"The current bulk element (right) marked as halo was not "
2623 <<
"found in the vector of halo\nelements associated with "
2624 <<
"the (" << right_processor <<
") processor.\n\n";
2626 "TriangleMesh::compute_boundary_segments_"
2627 "connectivity_and_initial_zeta_values()",
2628 OOMPH_EXCEPTION_LOCATION);
2634 right_face_ele_pt = segment_sorted_nonhalo_ele_pt[is].back();
2637 tmp_right_bulk_ele_pt = face_to_bulk_element_pt[right_face_ele_pt];
2640 if (tmp_right_bulk_ele_pt->
is_halo())
2642 std::ostringstream error_message;
2644 <<
"The bulk element represetation of the right-most nonhalo face\n"
2645 <<
"element of the current segment (" << is
2646 <<
") is marked as halo,\n"
2647 <<
"but the face element created from it is nonhalo\n";
2649 "TriangleMesh::compute_boundary_segments_"
2650 "connectivity_and_initial_zeta_values()",
2651 OOMPH_EXCEPTION_LOCATION);
2657 right_element_pt = tmp_right_bulk_ele_pt;
2661 bool right_haloed_element_found =
false;
2666 this->haloed_element_pt(right_processor);
2668 const unsigned nhaloed_right = right_haloed_element_pt.size();
2669 for (
unsigned rhd = 0; rhd < nhaloed_right; rhd++)
2671 if (right_element_pt == right_haloed_element_pt[rhd])
2673 right_haloed_element[is] = rhd;
2675 right_haloed_element_found =
true;
2682 if (!right_haloed_element_found)
2684 std::ostringstream error_message;
2686 <<
"The current bulk element (right) marked as haloed was not "
2687 <<
"found in the vector of haloed\nelements associated with "
2688 <<
"the (" << right_processor <<
") processor.\n\n";
2690 "TriangleMesh::compute_boundary_segments_"
2691 "connectivity_and_initial_zeta_values()",
2692 OOMPH_EXCEPTION_LOCATION);
2700 right_processor_plus_one[is] = 0;
2702 right_halo_element[is] = 0;
2704 right_haloed_element[is] = 0;
2720 const unsigned root_processor = 0;
2727 unsigned nsegments_mpi = nsegments;
2728 MPI_Gather(&nsegments_mpi,
2731 &root_nsegments_per_processor[0],
2735 comm_pt->mpi_comm());
2743 const unsigned spu = 7;
2745 for (
unsigned is = 0; is < nsegments; is++)
2747 flat_packed_unsigned_send_data[(spu * is) + 0] =
2748 left_processor_plus_one[is];
2749 flat_packed_unsigned_send_data[(spu * is) + 1] =
2750 right_processor_plus_one[is];
2751 flat_packed_unsigned_send_data[(spu * is) + 2] = left_halo_element[is];
2752 flat_packed_unsigned_send_data[(spu * is) + 3] = right_halo_element[is];
2753 flat_packed_unsigned_send_data[(spu * is) + 4] = left_haloed_element[is];
2754 flat_packed_unsigned_send_data[(spu * is) + 5] = right_haloed_element[is];
2755 flat_packed_unsigned_send_data[(spu * is) + 6] =
2756 nvertices_per_segment[is];
2760 const unsigned nudata_to_send = flat_packed_unsigned_send_data.size();
2766 unsigned root_nutotal_data_receive = 0;
2767 for (
unsigned ip = 0; ip < nproc; ip++)
2771 root_nudata_to_receive[ip] = root_nsegments_per_processor[ip] * spu;
2773 root_nutotal_data_receive += root_nudata_to_receive[ip];
2779 root_uoffsets_receive[0] = 0;
2780 for (
unsigned ip = 1; ip < nproc; ip++)
2783 root_uoffsets_receive[ip] =
2784 root_uoffsets_receive[ip - 1] + root_nudata_to_receive[ip - 1];
2788 if (flat_packed_unsigned_send_data.size() == 0)
2790 flat_packed_unsigned_send_data.resize(1);
2795 root_nutotal_data_receive);
2796 if (my_rank != root_processor)
2799 if (flat_packed_unsigned_receive_data.size() == 0)
2801 flat_packed_unsigned_receive_data.resize(1);
2805 MPI_Gatherv(&flat_packed_unsigned_send_data[0],
2811 &flat_packed_unsigned_receive_data[0],
2816 &root_nudata_to_receive[0],
2818 &root_uoffsets_receive[0],
2823 comm_pt->mpi_comm());
2826 flat_packed_unsigned_send_data.clear();
2827 flat_packed_unsigned_send_data.resize(0);
2833 const unsigned spd = 1;
2835 for (
unsigned is = 0; is < nsegments; is++)
2837 flat_packed_double_send_data[(spd * is) + 0] = segment_arclength[is];
2841 const unsigned nddata_to_send = flat_packed_double_send_data.size();
2846 unsigned root_ndtotal_data_receive = 0;
2847 for (
unsigned ip = 0; ip < nproc; ip++)
2849 root_nddata_to_receive[ip] = root_nsegments_per_processor[ip] * spd;
2850 root_ndtotal_data_receive += root_nddata_to_receive[ip];
2856 root_doffsets_receive[0] = 0;
2857 for (
unsigned ip = 1; ip < nproc; ip++)
2860 root_doffsets_receive[ip] =
2861 root_doffsets_receive[ip - 1] + root_nddata_to_receive[ip - 1];
2865 if (flat_packed_double_send_data.size() == 0)
2867 flat_packed_double_send_data.resize(1);
2871 Vector<double> flat_packed_double_receive_data(root_ndtotal_data_receive);
2872 if (my_rank != root_processor)
2875 if (flat_packed_double_receive_data.size() == 0)
2877 flat_packed_double_receive_data.resize(1);
2881 MPI_Gatherv(&flat_packed_double_send_data[0],
2887 &flat_packed_double_receive_data[0],
2891 &root_nddata_to_receive[0],
2893 &root_doffsets_receive[0],
2898 comm_pt->mpi_comm());
2901 flat_packed_double_send_data.clear();
2902 flat_packed_double_send_data.resize(0);
2924 double root_accumulated_arclength = 0.0;
2928 unsigned root_accumulated_vertices_before_segment = 0;
2932 if (my_rank == root_processor)
2978 unsigned ucounter = 0;
2979 unsigned dcounter = 0;
2980 for (
unsigned ip = 0; ip < nproc; ip++)
2983 const unsigned nsegs_iproc = root_nsegments_per_processor[ip];
2985 root_left_processor_plus_one[ip].resize(nsegs_iproc);
2986 root_right_processor_plus_one[ip].resize(nsegs_iproc);
2987 root_left_halo_element[ip].resize(nsegs_iproc);
2988 root_right_halo_element[ip].resize(nsegs_iproc);
2989 root_left_haloed_element[ip].resize(nsegs_iproc);
2990 root_right_haloed_element[ip].resize(nsegs_iproc);
2993 root_nvertices_per_segment[ip].resize(nsegs_iproc);
2994 root_segment_arclength[ip].resize(nsegs_iproc);
2995 root_segment_inverted[ip].resize(nsegs_iproc);
2999 for (
unsigned is = 0; is < nsegs_iproc; is++)
3002 root_left_processor_plus_one[ip][is] =
3003 flat_packed_unsigned_receive_data[ucounter++];
3004 root_right_processor_plus_one[ip][is] =
3005 flat_packed_unsigned_receive_data[ucounter++];
3006 root_left_halo_element[ip][is] =
3007 flat_packed_unsigned_receive_data[ucounter++];
3008 root_right_halo_element[ip][is] =
3009 flat_packed_unsigned_receive_data[ucounter++];
3010 root_left_haloed_element[ip][is] =
3011 flat_packed_unsigned_receive_data[ucounter++];
3012 root_right_haloed_element[ip][is] =
3013 flat_packed_unsigned_receive_data[ucounter++];
3014 root_nvertices_per_segment[ip][is] =
3015 flat_packed_unsigned_receive_data[ucounter++];
3018 root_segment_arclength[ip][is] =
3019 flat_packed_double_receive_data[dcounter++];
3030 for (
unsigned ip = 0; ip < nproc; ip++)
3032 const unsigned nsegs_iproc = root_nsegments_per_processor[ip];
3033 left_connected_segment_plus_one[ip].resize(nsegs_iproc, -1);
3034 right_connected_segment_plus_one[ip].resize(nsegs_iproc, -1);
3039 std::list<std::pair<unsigned, unsigned>> proc_seg_connectivity;
3040 proc_seg_connectivity.clear();
3043 std::map<std::pair<unsigned, unsigned>,
bool> done_segment;
3047 unsigned left_proc = 0;
3048 unsigned right_proc = 0;
3049 unsigned left_seg = 0;
3050 unsigned right_seg = 0;
3051 for (
unsigned ip = 0; ip < nproc; ip++)
3053 const unsigned nsegs_iproc = root_nsegments_per_processor[ip];
3054 if (nsegs_iproc > 0)
3056 right_proc = left_proc = ip;
3057 right_seg = left_seg = 0;
3064 std::pair<unsigned, unsigned> add_segment =
3065 std::make_pair(left_proc, left_seg);
3066 done_segment[add_segment] =
true;
3067 proc_seg_connectivity.push_back(add_segment);
3071 bool added_segment_to_the_left =
false;
3072 bool added_segment_to_the_right =
false;
3077 std::pair<unsigned, unsigned> left_pair = proc_seg_connectivity.front();
3078 left_proc = left_pair.first;
3079 left_seg = left_pair.second;
3083 const unsigned new_left_proc =
3084 root_left_processor_plus_one[left_proc][left_seg];
3086 if (new_left_proc != 0)
3089 added_segment_to_the_left =
false;
3091 const unsigned left_halo_id =
3092 root_left_halo_element[left_proc][left_seg];
3095 const unsigned left_haloed_id =
3096 root_left_haloed_element[left_proc][left_seg];
3100 const unsigned nsegs_new_left_proc =
3101 root_nsegments_per_processor[new_left_proc - 1];
3103 for (
unsigned ils = 0; ils < nsegs_new_left_proc; ils++)
3105 std::pair<unsigned, unsigned> candidate_seg =
3106 std::make_pair(new_left_proc - 1, ils);
3109 if (!done_segment[candidate_seg])
3113 const unsigned right_proc_of_new_left_proc =
3114 root_right_processor_plus_one[new_left_proc - 1][ils];
3117 const unsigned left_proc_of_new_left_proc =
3118 root_left_processor_plus_one[new_left_proc - 1][ils];
3121 if (right_proc_of_new_left_proc != 0 &&
3122 right_proc_of_new_left_proc - 1 == left_proc)
3127 const unsigned right_halo_id =
3128 root_right_halo_element[new_left_proc - 1][ils];
3129 const unsigned right_haloed_id =
3130 root_right_haloed_element[new_left_proc - 1][ils];
3131 if (left_halo_id == right_haloed_id &&
3132 left_haloed_id == right_halo_id)
3136 left_connected_segment_plus_one[left_proc][left_seg] =
3139 proc_seg_connectivity.push_front(candidate_seg);
3140 added_segment_to_the_left =
true;
3146 if (left_proc_of_new_left_proc != 0 &&
3147 left_proc_of_new_left_proc - 1 == left_proc)
3152 const unsigned inv_left_halo_id =
3153 root_left_halo_element[new_left_proc - 1][ils];
3154 const unsigned inv_left_haloed_id =
3155 root_left_haloed_element[new_left_proc - 1][ils];
3156 if (left_halo_id == inv_left_haloed_id &&
3157 left_haloed_id == inv_left_halo_id)
3161 left_connected_segment_plus_one[left_proc][left_seg] =
3164 proc_seg_connectivity.push_front(candidate_seg);
3168 const unsigned tmp_proc =
3169 root_left_processor_plus_one[new_left_proc - 1][ils];
3170 const unsigned tmp_halo =
3171 root_left_halo_element[new_left_proc - 1][ils];
3172 const unsigned tmp_haloed =
3173 root_left_haloed_element[new_left_proc - 1][ils];
3175 root_left_processor_plus_one[new_left_proc - 1][ils] =
3176 root_right_processor_plus_one[new_left_proc - 1][ils];
3177 root_left_halo_element[new_left_proc - 1][ils] =
3178 root_right_halo_element[new_left_proc - 1][ils];
3179 root_left_haloed_element[new_left_proc - 1][ils] =
3180 root_right_haloed_element[new_left_proc - 1][ils];
3182 root_right_processor_plus_one[new_left_proc - 1][ils] =
3184 root_right_halo_element[new_left_proc - 1][ils] = tmp_halo;
3185 root_right_haloed_element[new_left_proc - 1][ils] =
3190 root_segment_inverted[new_left_proc - 1][ils] = 1;
3192 added_segment_to_the_left =
true;
3200 if (!added_segment_to_the_left)
3202 std::ostringstream error_message;
3204 <<
"The corresponding processor and segment to the left of "
3205 <<
"the current left\nmost segment was not found\n";
3207 "TriangleMesh::compute_boundary_segments_"
3208 "connectivity_and_initial_zeta_values()",
3209 OOMPH_EXCEPTION_LOCATION);
3216 added_segment_to_the_left =
false;
3220 std::pair<unsigned, unsigned> right_pair = proc_seg_connectivity.back();
3221 right_proc = right_pair.first;
3222 right_seg = right_pair.second;
3226 const unsigned new_right_proc =
3227 root_right_processor_plus_one[right_proc][right_seg];
3229 if (new_right_proc != 0)
3232 added_segment_to_the_right =
false;
3234 const unsigned right_halo_id =
3235 root_right_halo_element[right_proc][right_seg];
3238 const unsigned right_haloed_id =
3239 root_right_haloed_element[right_proc][right_seg];
3243 const unsigned nsegs_new_right_proc =
3244 root_nsegments_per_processor[new_right_proc - 1];
3246 for (
unsigned irs = 0; irs < nsegs_new_right_proc; irs++)
3248 std::pair<unsigned, unsigned> candidate_seg =
3249 std::make_pair(new_right_proc - 1, irs);
3252 if (!done_segment[candidate_seg])
3256 const unsigned left_proc_of_new_right_proc =
3257 root_left_processor_plus_one[new_right_proc - 1][irs];
3260 const unsigned right_proc_of_new_right_proc =
3261 root_right_processor_plus_one[new_right_proc - 1][irs];
3264 if (left_proc_of_new_right_proc != 0 &&
3265 left_proc_of_new_right_proc - 1 == right_proc)
3270 const unsigned left_halo_id =
3271 root_left_halo_element[new_right_proc - 1][irs];
3272 const unsigned left_haloed_id =
3273 root_left_haloed_element[new_right_proc - 1][irs];
3275 if (right_halo_id == left_haloed_id &&
3276 right_haloed_id == left_halo_id)
3280 right_connected_segment_plus_one[right_proc][right_seg] =
3283 proc_seg_connectivity.push_back(candidate_seg);
3284 added_segment_to_the_right =
true;
3290 if (right_proc_of_new_right_proc != 0 &&
3291 right_proc_of_new_right_proc - 1 == right_proc)
3297 const unsigned inv_right_halo_id =
3298 root_right_halo_element[new_right_proc - 1][irs];
3299 const unsigned inv_right_haloed_id =
3300 root_right_haloed_element[new_right_proc - 1][irs];
3301 if (right_halo_id == inv_right_haloed_id &&
3302 right_haloed_id == inv_right_halo_id)
3306 right_connected_segment_plus_one[right_proc][right_seg] =
3309 proc_seg_connectivity.push_back(candidate_seg);
3312 const unsigned tmp_proc =
3313 root_left_processor_plus_one[new_right_proc - 1][irs];
3314 const unsigned tmp_halo =
3315 root_left_halo_element[new_right_proc - 1][irs];
3316 const unsigned tmp_haloed =
3317 root_left_haloed_element[new_right_proc - 1][irs];
3319 root_left_processor_plus_one[new_right_proc - 1][irs] =
3320 root_right_processor_plus_one[new_right_proc - 1][irs];
3321 root_left_halo_element[new_right_proc - 1][irs] =
3322 root_right_halo_element[new_right_proc - 1][irs];
3323 root_left_haloed_element[new_right_proc - 1][irs] =
3324 root_right_haloed_element[new_right_proc - 1][irs];
3326 root_right_processor_plus_one[new_right_proc - 1][irs] =
3328 root_right_halo_element[new_right_proc - 1][irs] = tmp_halo;
3329 root_right_haloed_element[new_right_proc - 1][irs] =
3334 root_segment_inverted[new_right_proc - 1][irs] = 1;
3336 added_segment_to_the_right =
true;
3344 if (!added_segment_to_the_right)
3346 std::ostringstream error_message;
3348 <<
"The corresponding processor and segment to the right of "
3349 <<
"the current right\nmost segment was not found\n";
3351 "TriangleMesh::compute_boundary_segments_"
3352 "connectivity_and_initial_zeta_values()",
3353 OOMPH_EXCEPTION_LOCATION);
3360 added_segment_to_the_right =
false;
3363 }
while (added_segment_to_the_left || added_segment_to_the_right);
3371 const unsigned ntotal_segments = proc_seg_connectivity.size();
3373 unsigned tmp_total_segments = 0;
3374 for (
unsigned ip = 0; ip < nproc; ip++)
3376 tmp_total_segments += root_nsegments_per_processor[ip];
3381 if (ntotal_segments != tmp_total_segments)
3383 std::ostringstream error_message;
3384 error_message <<
"The number of sorted segments (" << ntotal_segments
3386 <<
"boundary (" << b
3387 <<
")\nis different from the total number of "
3388 <<
"segments (" << tmp_total_segments
3389 <<
") in all\nprocessors.\n\n";
3391 OOMPH_CURRENT_FUNCTION,
3392 OOMPH_EXCEPTION_LOCATION);
3401 for (
unsigned ip = 0; ip < nproc; ip++)
3403 const unsigned nsegs_iproc = root_nsegments_per_processor[ip];
3404 root_initial_segment_arclength[ip].resize(nsegs_iproc);
3405 root_nvertices_before_segment[ip].resize(nsegs_iproc);
3412 for (std::list<std::pair<unsigned, unsigned>>::iterator it_list =
3413 proc_seg_connectivity.begin();
3414 it_list != proc_seg_connectivity.end();
3417 const unsigned iproc =
static_cast<unsigned>((*it_list).first);
3418 const unsigned iseg =
static_cast<unsigned>((*it_list).second);
3419 const double iseg_arclength = root_segment_arclength[iproc][iseg];
3420 const unsigned iseg_nvertices = root_nvertices_per_segment[iproc][iseg];
3422 aux_initial_segment_arclength[ucounter] = root_accumulated_arclength;
3423 aux_nvertices_before_segment[ucounter] =
3424 root_accumulated_vertices_before_segment;
3427 root_initial_segment_arclength[iproc][iseg] =
3428 root_accumulated_arclength;
3430 root_nvertices_before_segment[iproc][iseg] =
3431 root_accumulated_vertices_before_segment;
3434 root_accumulated_arclength += iseg_arclength;
3436 root_accumulated_vertices_before_segment += iseg_nvertices - 1;
3445 root_accumulated_vertices_before_segment++;
3448 proc_with_initial_seg = proc_seg_connectivity.front().first;
3449 proc_with_final_seg = proc_seg_connectivity.back().first;
3452 initial_segment = proc_seg_connectivity.front().second;
3453 final_segment = proc_seg_connectivity.back().second;
3458 unsigned root_ntotal_segments = 0;
3459 for (
unsigned ip = 0; ip < nproc; ip++)
3461 root_ntotal_segments += root_nsegments_per_processor[ip];
3468 const unsigned rspu = 2;
3469 flat_packed_unsigned_send_data.clear();
3470 flat_packed_unsigned_send_data.resize(root_ntotal_segments * rspu);
3471 unsigned ucounter = 0;
3473 for (
unsigned ip = 0; ip < nproc; ip++)
3475 const unsigned nsegs_iproc = root_nsegments_per_processor[ip];
3476 for (
unsigned is = 0; is < nsegs_iproc; is++)
3478 flat_packed_unsigned_send_data[ucounter++] =
3479 root_nvertices_before_segment[ip][is];
3480 flat_packed_unsigned_send_data[ucounter++] =
3481 root_segment_inverted[ip][is];
3487 for (
unsigned ip = 0; ip < nproc; ip++)
3490 root_nudata_to_send[ip] = root_nsegments_per_processor[ip] * rspu;
3495 root_uoffsets_send[0] = 0;
3496 for (
unsigned ip = 1; ip < nproc; ip++)
3499 root_uoffsets_send[ip] =
3500 root_uoffsets_send[ip - 1] + root_nudata_to_send[ip - 1];
3504 unsigned nutotal_data_receive = nsegments * rspu;
3506 if (my_rank != root_processor)
3509 if (flat_packed_unsigned_send_data.size() == 0)
3511 flat_packed_unsigned_send_data.resize(1);
3516 flat_packed_unsigned_receive_data.clear();
3517 flat_packed_unsigned_receive_data.resize(nutotal_data_receive);
3519 if (flat_packed_unsigned_receive_data.size() == 0)
3521 flat_packed_unsigned_receive_data.resize(1);
3524 MPI_Scatterv(&flat_packed_unsigned_send_data[0],
3525 &root_nudata_to_send[0],
3526 &root_uoffsets_send[0],
3528 &flat_packed_unsigned_receive_data[0],
3529 nutotal_data_receive,
3532 comm_pt->mpi_comm());
3537 const unsigned rspd = 1;
3538 flat_packed_double_send_data.clear();
3539 flat_packed_double_send_data.resize(root_ntotal_segments * rspd);
3540 unsigned dcounter = 0;
3542 for (
unsigned ip = 0; ip < nproc; ip++)
3544 const unsigned nsegs_iproc = root_nsegments_per_processor[ip];
3545 for (
unsigned is = 0; is < nsegs_iproc; is++)
3547 flat_packed_double_send_data[dcounter++] =
3548 root_initial_segment_arclength[ip][is];
3554 for (
unsigned ip = 0; ip < nproc; ip++)
3557 root_nddata_to_send[ip] = root_nsegments_per_processor[ip] * rspd;
3562 root_doffsets_send[0] = 0;
3563 for (
unsigned ip = 1; ip < nproc; ip++)
3566 root_doffsets_send[ip] =
3567 root_doffsets_send[ip - 1] + root_nddata_to_send[ip - 1];
3571 unsigned ndtotal_data_receive = nsegments * rspd;
3573 if (my_rank != root_processor)
3576 if (flat_packed_double_send_data.size() == 0)
3578 flat_packed_double_send_data.resize(1);
3583 flat_packed_double_receive_data.clear();
3584 flat_packed_double_receive_data.resize(ndtotal_data_receive);
3586 if (flat_packed_double_receive_data.size() == 0)
3588 flat_packed_double_receive_data.resize(1);
3591 MPI_Scatterv(&flat_packed_double_send_data[0],
3592 &root_nddata_to_send[0],
3593 &root_doffsets_send[0],
3595 &flat_packed_double_receive_data[0],
3596 ndtotal_data_receive,
3599 comm_pt->mpi_comm());
3608 for (
unsigned is = 0; is < nsegments; is++)
3611 nvertices_before_segment[is] =
3612 flat_packed_unsigned_receive_data[ucounter++];
3614 segment_inverted[is] = flat_packed_unsigned_receive_data[ucounter++];
3616 initial_segment_arclength[is] =
3617 flat_packed_double_receive_data[dcounter++];
3623 const unsigned numore_info = 5;
3626 flat_package_unsigned_more_info[0] =
3627 root_accumulated_vertices_before_segment;
3628 flat_package_unsigned_more_info[1] = proc_with_initial_seg;
3629 flat_package_unsigned_more_info[2] = proc_with_final_seg;
3630 flat_package_unsigned_more_info[3] = initial_segment;
3631 flat_package_unsigned_more_info[4] = final_segment;
3634 MPI_Bcast(&flat_package_unsigned_more_info[0],
3638 comm_pt->mpi_comm());
3641 root_accumulated_vertices_before_segment =
3642 flat_package_unsigned_more_info[0];
3643 proc_with_initial_seg = flat_package_unsigned_more_info[1];
3644 proc_with_final_seg = flat_package_unsigned_more_info[2];
3645 initial_segment = flat_package_unsigned_more_info[3];
3646 final_segment = flat_package_unsigned_more_info[4];
3649 MPI_Bcast(&root_accumulated_arclength,
3653 comm_pt->mpi_comm());
3662 Boundary_initial_coordinate[b].clear();
3663 Boundary_final_coordinate[b].clear();
3665 Boundary_initial_zeta_coordinate[b].clear();
3666 Boundary_final_zeta_coordinate[b].clear();
3669 Boundary_segment_inverted[b].clear();
3670 Boundary_segment_initial_coordinate[b].clear();
3671 Boundary_segment_final_coordinate[b].clear();
3673 Boundary_segment_initial_zeta[b].clear();
3674 Boundary_segment_final_zeta[b].clear();
3676 Boundary_segment_initial_arclength[b].clear();
3677 Boundary_segment_final_arclength[b].clear();
3681 for (
unsigned is = 0; is < nsegments; is++)
3694 segment_sorted_nonhalo_ele_pt[is].front();
3699 if (first_seg_ele_pt->
is_halo())
3701 std::ostringstream error_message;
3702 error_message <<
"The first face element in the (" << is
3703 <<
")-th segment is halo\n";
3705 "TriangleMesh::compute_boundary_segments_"
3706 "connectivity_and_initial_zeta_values()",
3707 OOMPH_EXCEPTION_LOCATION);
3712 const unsigned nnod = first_seg_ele_pt->
nnode();
3715 Node* first_seg_node_pt = first_seg_ele_pt->
node_pt(0);
3716 if (is_inverted[first_seg_ele_pt])
3718 first_seg_node_pt = first_seg_ele_pt->
node_pt(nnod - 1);
3722 FiniteElement* last_seg_ele_pt = segment_sorted_nonhalo_ele_pt[is].back();
3727 if (last_seg_ele_pt->
is_halo())
3729 std::ostringstream error_message;
3730 error_message <<
"The last face element in the (" << is
3731 <<
")-th segment is halo\n";
3733 "TriangleMesh::compute_boundary_segments_"
3734 "connectivity_and_initial_zeta_values()",
3735 OOMPH_EXCEPTION_LOCATION);
3740 Node* last_seg_node_pt = last_seg_ele_pt->
node_pt(nnod - 1);
3741 if (is_inverted[last_seg_ele_pt])
3743 last_seg_node_pt = last_seg_ele_pt->
node_pt(0);
3747 for (
unsigned i = 0;
i < 2;
i++)
3749 first_seg_coord[
i] = first_seg_node_pt->x(
i);
3750 last_seg_coord[
i] = last_seg_node_pt->x(
i);
3755 Boundary_segment_inverted[b].push_back(segment_inverted[is]);
3759 if (!segment_inverted[is])
3763 Boundary_segment_initial_coordinate[b].push_back(first_seg_coord);
3764 Boundary_segment_final_coordinate[b].push_back(last_seg_coord);
3771 Boundary_segment_initial_coordinate[b].push_back(last_seg_coord);
3772 Boundary_segment_final_coordinate[b].push_back(first_seg_coord);
3779 if (boundary_geom_object_pt(b) != 0)
3784 if (segment_inverted[is])
3786 Boundary_segment_initial_zeta[b].push_back(final_zeta_segment[is]);
3787 Boundary_segment_final_zeta[b].push_back(initial_zeta_segment[is]);
3791 Boundary_segment_initial_zeta[b].push_back(initial_zeta_segment[is]);
3792 Boundary_segment_final_zeta[b].push_back(final_zeta_segment[is]);
3799 Boundary_segment_initial_arclength[b].push_back(
3800 initial_segment_arclength[is]);
3802 Boundary_segment_final_arclength[b].push_back(
3803 initial_segment_arclength[is] + segment_arclength[is]);
3811 if (segment_all_nodes_pt.size() != nsegments)
3813 std::ostringstream error_message;
3814 error_message <<
"The number of segments (" << nsegments
3815 <<
") and the number of "
3816 <<
"set of nodes (" << segment_all_nodes_pt.size()
3817 <<
") representing\n"
3818 <<
"the\nsegments is different!!!\n\n";
3820 "TriangleMesh::compute_boundary_segments_"
3821 "connectivity_and_initial_zeta_values()",
3822 OOMPH_EXCEPTION_LOCATION);
3846 const unsigned ndtotal_data = 3;
3847 Vector<double> flat_packed_double_data_initial_seg(ndtotal_data);
3851 if (my_rank == proc_with_initial_seg)
3856 Node* first_node_pt = 0;
3858 if (!segment_inverted[initial_segment])
3862 first_ele_pt = segment_sorted_ele_pt[initial_segment].front();
3865 const unsigned nnod = first_ele_pt->
nnode();
3868 first_node_pt = first_ele_pt->
node_pt(0);
3869 if (is_inverted[first_ele_pt])
3871 first_node_pt = first_ele_pt->node_pt(nnod - 1);
3878 first_ele_pt = segment_sorted_ele_pt[initial_segment].back();
3881 const unsigned nnod = first_ele_pt->
nnode();
3884 first_node_pt = first_ele_pt->
node_pt(nnod - 1);
3885 if (is_inverted[first_ele_pt])
3887 first_node_pt = first_ele_pt->node_pt(0);
3892 for (
unsigned i = 0;
i < 2;
i++)
3894 flat_packed_double_data_initial_seg[
i] = first_node_pt->x(
i);
3899 first_node_pt->get_coordinates_on_boundary(b, tmp_zeta);
3903 if (this->boundary_geom_object_pt(b) != 0)
3911 if (tmp_zeta[0] >= 1.0e-14)
3918 flat_packed_double_data_initial_seg[2] = tmp_zeta[0];
3924 MPI_Bcast(&flat_packed_double_data_initial_seg[0],
3927 proc_with_initial_seg,
3928 comm_pt->mpi_comm());
3932 for (
unsigned i = 0;
i < 2;
i++)
3934 first_coordinate[
i] = flat_packed_double_data_initial_seg[
i];
3936 first_node_zeta_coordinate[0] = flat_packed_double_data_initial_seg[2];
3945 if (my_rank == proc_with_final_seg)
3951 Node* last_node_pt = 0;
3954 if (!segment_inverted[final_segment])
3958 last_ele_pt = segment_sorted_ele_pt[final_segment].back();
3961 const unsigned nnod = last_ele_pt->
nnode();
3964 last_node_pt = last_ele_pt->
node_pt(nnod - 1);
3965 if (is_inverted[last_ele_pt])
3967 last_node_pt = last_ele_pt->node_pt(0);
3974 last_ele_pt = segment_sorted_ele_pt[final_segment].front();
3977 const unsigned nnod = last_ele_pt->
nnode();
3980 last_node_pt = last_ele_pt->
node_pt(0);
3981 if (is_inverted[last_ele_pt])
3983 last_node_pt = last_ele_pt->node_pt(nnod - 1);
3988 for (
unsigned i = 0;
i < 2;
i++)
3990 flat_packed_double_data_final_seg[
i] = last_node_pt->x(
i);
3995 last_node_pt->get_coordinates_on_boundary(b, tmp_zeta);
3999 if (this->boundary_geom_object_pt(b) != 0)
4008 if (std::fabs(tmp_zeta[0] - root_accumulated_arclength) >= 1.0e-14)
4010 tmp_zeta[0] = root_accumulated_arclength;
4015 flat_packed_double_data_final_seg[2] = tmp_zeta[0];
4021 MPI_Bcast(&flat_packed_double_data_final_seg[0],
4024 proc_with_final_seg,
4025 comm_pt->mpi_comm());
4029 for (
unsigned i = 0;
i < 2;
i++)
4031 last_coordinate[
i] = flat_packed_double_data_final_seg[
i];
4033 last_node_zeta_coordinate[0] = flat_packed_double_data_final_seg[2];
4037 Boundary_initial_coordinate[b] = first_coordinate;
4038 Boundary_final_coordinate[b] = last_coordinate;
4040 Boundary_initial_zeta_coordinate[b] = first_node_zeta_coordinate;
4041 Boundary_final_zeta_coordinate[b] = last_node_zeta_coordinate;
4045 if (is_internal_boundary)
4056 re_assign_initial_zeta_values_for_internal_boundary(
4057 b, segment_sorted_nonhalo_ele_pt, is_inverted);
4068 identify_boundary_segments_and_assign_initial_zeta_values(b,
this);
4072 for (
unsigned i = 0;
i < n_all_face_ele;
i++)
4074 delete all_face_ele_pt[
i];
4075 all_face_ele_pt[
i] = 0;
4087 template<
class ELEMENT>
4091 Vector<std::list<FiniteElement*>>& old_segment_sorted_ele_pt,
4092 std::map<FiniteElement*, bool>& old_is_inverted)
4107 unsigned n_repeated_ele = 0;
4109 const unsigned n_regions = this->nregion();
4118 for (
unsigned rr = 0; rr < n_regions; rr++)
4120 const unsigned region_id =
4121 static_cast<unsigned>(this->Region_attribute[rr]);
4124 const unsigned nel_in_region =
4125 this->nboundary_element_in_region(b, region_id);
4127 unsigned nel_repetead_in_region = 0;
4131 if (nel_in_region > 0)
4133 bool repeated =
false;
4136 for (
unsigned e = 0;
e < nel_in_region;
e++)
4141 this->boundary_element_in_region_pt(b, region_id,
e);
4152 this->face_index_at_boundary_in_region(b, region_id,
e);
4160 const unsigned n_nodes = tmp_ele_pt->
nnode();
4162 std::pair<Node*, Node*> tmp_pair = std::make_pair(
4165 std::pair<Node*, Node*> tmp_pair_inverse = std::make_pair(
4169 const unsigned repeated_nodes_size = done_nodes_pt.size();
4170 for (
unsigned l = 0; l < repeated_nodes_size; l++)
4172 if (tmp_pair == done_nodes_pt[l] ||
4173 tmp_pair_inverse == done_nodes_pt[l])
4175 nel_repetead_in_region++;
4185 done_nodes_pt.push_back(tmp_pair);
4187 face_el_pt.push_back(tmp_ele_pt);
4201 nele += nel_in_region;
4203 n_repeated_ele += nel_repetead_in_region;
4212 nele = this->nboundary_element(b);
4218 bool repeated =
false;
4221 for (
unsigned e = 0;
e < nele;
e++)
4235 int face_index = this->face_index_at_boundary(b,
e);
4243 const unsigned n_nodes = tmp_ele_pt->
nnode();
4245 std::pair<Node*, Node*> tmp_pair = std::make_pair(
4248 std::pair<Node*, Node*> tmp_pair_inverse = std::make_pair(
4252 const unsigned repeated_nodes_size = done_nodes_pt.size();
4253 for (
unsigned l = 0; l < repeated_nodes_size; l++)
4255 if (tmp_pair == done_nodes_pt[l] ||
4256 tmp_pair_inverse == done_nodes_pt[l])
4270 done_nodes_pt.push_back(tmp_pair);
4272 face_el_pt.push_back(tmp_ele_pt);
4290 nele -= n_repeated_ele;
4293 if (nele != face_el_pt.size())
4295 std::ostringstream error_message;
4297 <<
"The independet counting of face elements (" << nele <<
") for "
4298 <<
"boundary (" << b <<
") is different\n"
4299 <<
"from the real number of face elements in the container ("
4300 << face_el_pt.size() <<
")\n";
4303 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
4312 const unsigned nnon_halo_face_elements = face_el_pt.size();
4319 unsigned nsorted_face_elements = 0;
4322 std::map<FiniteElement*, bool> done_el;
4325 std::map<FiniteElement*, bool> is_inverted;
4328 while (nsorted_face_elements < nnon_halo_face_elements)
4332 std::list<FiniteElement*> sorted_el_pt;
4336 bool found_initial_face_element =
false;
4342 for (iface = 0; iface < nele; iface++)
4344 ele_face_pt = face_el_pt[iface];
4346 if (!done_el[ele_face_pt])
4350 found_initial_face_element =
true;
4353 nsorted_face_elements++;
4358 sorted_el_pt.push_back(ele_face_pt);
4360 done_el[ele_face_pt] =
true;
4366 if (!found_initial_face_element)
4368 std::ostringstream error_message;
4370 <<
"Could not find an initial face element for the current segment\n";
4372 error_message.str(),
4373 "TriangleMesh::re_assign_initial_zeta_values_for_internal_boundary()",
4374 OOMPH_EXCEPTION_LOCATION);
4379 const unsigned nnod = ele_face_pt->
nnode();
4383 Node* left_node_pt = ele_face_pt->
node_pt(0);
4384 Node* right_node_pt = ele_face_pt->
node_pt(nnod - 1);
4388 bool face_element_added =
false;
4397 for (
unsigned iiface = iface; iiface < nele; iiface++)
4400 face_element_added =
false;
4403 ele_face_pt = face_el_pt[iiface];
4407 if (!(done_el[ele_face_pt]))
4410 Node* local_left_node_pt = ele_face_pt->node_pt(0);
4411 Node* local_right_node_pt = ele_face_pt->node_pt(nnod - 1);
4414 if (left_node_pt == local_right_node_pt)
4416 left_node_pt = local_left_node_pt;
4417 sorted_el_pt.push_front(ele_face_pt);
4418 is_inverted[ele_face_pt] =
false;
4419 face_element_added =
true;
4422 else if (left_node_pt == local_left_node_pt)
4424 left_node_pt = local_right_node_pt;
4425 sorted_el_pt.push_front(ele_face_pt);
4426 is_inverted[ele_face_pt] =
true;
4427 face_element_added =
true;
4430 else if (right_node_pt == local_left_node_pt)
4432 right_node_pt = local_right_node_pt;
4433 sorted_el_pt.push_back(ele_face_pt);
4434 is_inverted[ele_face_pt] =
false;
4435 face_element_added =
true;
4438 else if (right_node_pt == local_right_node_pt)
4440 right_node_pt = local_left_node_pt;
4441 sorted_el_pt.push_back(ele_face_pt);
4442 is_inverted[ele_face_pt] =
true;
4443 face_element_added =
true;
4446 if (face_element_added)
4448 done_el[ele_face_pt] =
true;
4449 nsorted_face_elements++;
4457 }
while (face_element_added &&
4458 (nsorted_face_elements < nnon_halo_face_elements));
4461 segment_sorted_ele_pt.push_back(sorted_el_pt);
4472 const unsigned nsegments = segment_sorted_ele_pt.size();
4475 if (nnon_halo_face_elements > 0 && nsegments == 0)
4477 std::ostringstream error_message;
4479 <<
"The number of segments is zero, but the number of nonhalo\n"
4480 <<
"elements is: (" << nnon_halo_face_elements <<
")\n";
4482 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
4514 for (
unsigned is = 0; is < nsegments; is++)
4517 if (segment_sorted_ele_pt[is].size() == 0)
4519 std::ostringstream error_message;
4520 error_message <<
"The (" << is <<
")-th segment has no elements\n";
4522 error_message.str(),
4523 "TriangleMesh::re_assign_initial_zeta_values_for_internal_boundary()",
4524 OOMPH_EXCEPTION_LOCATION);
4529 FiniteElement* first_ele_pt = segment_sorted_ele_pt[is].front();
4532 const unsigned nnod = first_ele_pt->
nnode();
4535 Node* first_node_pt = first_ele_pt->
node_pt(0);
4536 if (is_inverted[first_ele_pt])
4538 first_node_pt = first_ele_pt->
node_pt(nnod - 1);
4542 double x_left = first_node_pt->x(0);
4543 double y_left = first_node_pt->x(1);
4552 if (this->boundary_geom_object_pt(b) != 0)
4554 first_node_pt->get_coordinates_on_boundary(b, zeta);
4555 initial_zeta_segment[is] = zeta[0];
4558 FiniteElement* last_ele_pt = segment_sorted_ele_pt[is].back();
4561 Node* last_node_pt = last_ele_pt->
node_pt(nnod - 1);
4562 if (is_inverted[last_ele_pt])
4564 last_node_pt = last_ele_pt->
node_pt(0);
4567 last_node_pt->get_coordinates_on_boundary(b, zeta);
4568 final_zeta_segment[is] = zeta[0];
4573 std::set<Node*> local_nodes_pt;
4574 local_nodes_pt.insert(first_node_pt);
4578 sorted_node_arclength.push_back(0.0);
4583 sorted_nodes_pt.push_back(first_node_pt);
4586 for (std::list<FiniteElement*>::iterator it =
4587 segment_sorted_ele_pt[is].begin();
4588 it != segment_sorted_ele_pt[is].end();
4597 if (is_inverted[el_pt])
4604 for (
unsigned j = 1; j < nnod; j++)
4606 Node* nod_pt = el_pt->
node_pt(k_nod);
4610 double x_right = nod_pt->x(0);
4611 double y_right = nod_pt->x(1);
4614 zeta[0] += sqrt((x_right - x_left) * (x_right - x_left) +
4615 (y_right - y_left) * (y_right - y_left));
4620 if (this->boundary_geom_object_pt(b) == 0)
4632 local_nodes_pt.insert(nod_pt);
4635 sorted_node_arclength.push_back(zeta[0]);
4638 sorted_nodes_pt.push_back(nod_pt);
4647 segment_arclength[is] = zeta[0];
4652 nvertices_per_segment[is] = local_nodes_pt.size();
4655 segment_all_nodes_pt[is] = local_nodes_pt;
4658 sorted_segment_node_arclength[is] = sorted_node_arclength;
4661 sorted_segment_all_nodes_pt[is] = sorted_nodes_pt;
4676 const unsigned old_nsegments = old_segment_sorted_ele_pt.size();
4689 Vector<double> old_boundary_segment_initial_arclength(old_nsegments);
4690 Vector<double> old_boundary_segment_final_arclength(old_nsegments);
4693 for (
unsigned old_is = 0; old_is < old_nsegments; old_is++)
4695 old_boundary_segment_inverted[old_is] =
4696 boundary_segment_inverted(b)[old_is];
4698 old_boundary_segment_initial_coordinate[old_is].resize(2);
4699 old_boundary_segment_final_coordinate[old_is].resize(2);
4700 for (
unsigned i = 0;
i < 2;
i++)
4702 old_boundary_segment_initial_coordinate[old_is][
i] =
4703 boundary_segment_initial_coordinate(b)[old_is][
i];
4705 old_boundary_segment_final_coordinate[old_is][
i] =
4706 boundary_segment_final_coordinate(b)[old_is][
i];
4710 if (this->boundary_geom_object_pt(b) != 0)
4712 old_boundary_segment_initial_zeta[old_is] =
4713 boundary_segment_initial_zeta(b)[old_is];
4715 old_boundary_segment_final_zeta[old_is] =
4716 boundary_segment_final_zeta(b)[old_is];
4721 old_boundary_segment_initial_arclength[old_is] =
4722 boundary_segment_initial_arclength(b)[old_is];
4724 old_boundary_segment_final_arclength[old_is] =
4725 boundary_segment_final_arclength(b)[old_is];
4733 Boundary_segment_inverted[b].clear();
4734 Boundary_segment_initial_coordinate[b].clear();
4735 Boundary_segment_final_coordinate[b].clear();
4737 Boundary_segment_initial_zeta[b].clear();
4738 Boundary_segment_final_zeta[b].clear();
4740 Boundary_segment_initial_arclength[b].clear();
4741 Boundary_segment_final_arclength[b].clear();
4744 Boundary_segment_inverted[b].resize(nsegments);
4745 Boundary_segment_initial_coordinate[b].resize(nsegments);
4746 Boundary_segment_final_coordinate[b].resize(nsegments);
4749 if (this->boundary_geom_object_pt(b) != 0)
4751 Boundary_segment_initial_zeta[b].resize(nsegments);
4752 Boundary_segment_final_zeta[b].resize(nsegments);
4756 Boundary_segment_initial_arclength[b].resize(nsegments);
4757 Boundary_segment_final_arclength[b].resize(nsegments);
4761 std::map<unsigned, bool> done_segment;
4764 unsigned re_assigned_segments = 0;
4767 for (
unsigned old_is = 0; old_is < old_nsegments; old_is++)
4770 const double old_initial_arclength =
4771 old_boundary_segment_initial_arclength[old_is];
4772 const double old_final_arclength =
4773 old_boundary_segment_final_arclength[old_is];
4775 const unsigned old_inverted_segment =
4776 old_boundary_segment_inverted[old_is];
4780 bool old_increasing_order =
false;
4781 if (old_initial_arclength < old_final_arclength)
4783 old_increasing_order =
true;
4789 old_segment_sorted_ele_pt[old_is].front();
4792 const unsigned nnod = first_old_seg_ele_pt->
nnode();
4795 Node* first_old_seg_node_pt = first_old_seg_ele_pt->
node_pt(0);
4796 if (old_is_inverted[first_old_seg_ele_pt])
4798 first_old_seg_node_pt = first_old_seg_ele_pt->
node_pt(nnod - 1);
4803 old_segment_sorted_ele_pt[old_is].back();
4806 Node* last_old_seg_node_pt = last_old_seg_ele_pt->
node_pt(nnod - 1);
4807 if (old_is_inverted[last_old_seg_ele_pt])
4809 last_old_seg_node_pt = last_old_seg_ele_pt->
node_pt(0);
4813 if (old_inverted_segment)
4815 Node* temp_node_pt = first_old_seg_node_pt;
4816 first_old_seg_node_pt = last_old_seg_node_pt;
4817 last_old_seg_node_pt = temp_node_pt;
4823 for (
unsigned is = 0; is < nsegments; is++)
4825 if (!done_segment[is])
4829 bool found_first_old_seg_node =
false;
4830 bool found_last_old_seg_node =
false;
4831 bool same_order =
false;
4834 FiniteElement* first_seg_ele_pt = segment_sorted_ele_pt[is].front();
4835 Node* first_seg_node_pt = first_seg_ele_pt->
node_pt(0);
4836 if (is_inverted[first_seg_ele_pt])
4838 first_seg_node_pt = first_seg_ele_pt->
node_pt(nnod - 1);
4842 const double segment_first_node_zeta =
4843 sorted_segment_node_arclength[is][0];
4847 for (
unsigned i = 0;
i < 2;
i++)
4849 first_node_coord[
i] = first_seg_node_pt->x(
i);
4853 FiniteElement* last_seg_ele_pt = segment_sorted_ele_pt[is].back();
4854 Node* last_seg_node_pt = last_seg_ele_pt->
node_pt(nnod - 1);
4855 if (is_inverted[last_seg_ele_pt])
4857 last_seg_node_pt = last_seg_ele_pt->
node_pt(0);
4861 const double segment_final_node_zeta = segment_arclength[is];
4865 for (
unsigned i = 0;
i < 2;
i++)
4867 last_node_coord[
i] = last_seg_node_pt->x(
i);
4871 Vector<Node*> segment_node_pt = sorted_segment_all_nodes_pt[is];
4873 const unsigned nsegment_node = segment_node_pt.size();
4874 for (
unsigned in = 0; in < nsegment_node; in++)
4876 Node* current_node_pt = segment_node_pt[in];
4877 if (!found_first_old_seg_node &&
4878 first_old_seg_node_pt == current_node_pt)
4882 const double current_node_zeta =
4883 sorted_segment_node_arclength[is][in];
4887 if (!found_last_old_seg_node)
4890 Boundary_segment_initial_coordinate[b][is] = first_node_coord;
4893 if (this->boundary_geom_object_pt(b) != 0)
4900 Boundary_segment_initial_zeta[b][is] =
4901 initial_zeta_segment[is];
4907 const double distance =
4908 std::fabs(current_node_zeta - segment_first_node_zeta);
4910 double new_initial_arclength = old_initial_arclength;
4913 if (old_increasing_order)
4916 new_initial_arclength -= distance;
4921 new_initial_arclength += distance;
4925 Boundary_segment_initial_arclength[b][is] =
4926 new_initial_arclength;
4933 Boundary_segment_initial_coordinate[b][is] = last_node_coord;
4936 if (this->boundary_geom_object_pt(b) != 0)
4944 Boundary_segment_initial_zeta[b][is] = final_zeta_segment[is];
4950 const double distance =
4951 std::fabs(current_node_zeta - segment_final_node_zeta);
4953 double new_initial_arclength = old_initial_arclength;
4956 if (old_increasing_order)
4959 new_initial_arclength -= distance;
4964 new_initial_arclength += distance;
4968 Boundary_segment_initial_arclength[b][is] =
4969 new_initial_arclength;
4975 found_first_old_seg_node =
true;
4982 if (found_first_old_seg_node && !found_last_old_seg_node)
4987 if (!found_last_old_seg_node &&
4988 last_old_seg_node_pt == current_node_pt)
4992 const double current_node_zeta =
4993 sorted_segment_node_arclength[is][in];
4997 if (found_first_old_seg_node)
5000 Boundary_segment_final_coordinate[b][is] = last_node_coord;
5003 if (this->boundary_geom_object_pt(b) != 0)
5010 Boundary_segment_final_zeta[b][is] = final_zeta_segment[is];
5016 const double distance =
5017 std::fabs(current_node_zeta - segment_final_node_zeta);
5019 double new_final_arclength = old_final_arclength;
5022 if (old_increasing_order)
5025 new_final_arclength += distance;
5030 new_final_arclength -= distance;
5034 Boundary_segment_final_arclength[b][is] = new_final_arclength;
5041 Boundary_segment_final_coordinate[b][is] = first_node_coord;
5044 if (this->boundary_geom_object_pt(b) != 0)
5052 Boundary_segment_final_zeta[b][is] = initial_zeta_segment[is];
5058 const double distance =
5059 std::fabs(current_node_zeta - segment_first_node_zeta);
5061 double new_final_arclength = old_final_arclength;
5064 if (old_increasing_order)
5067 new_final_arclength += distance;
5072 new_final_arclength -= distance;
5076 Boundary_segment_final_arclength[b][is] = new_final_arclength;
5082 found_last_old_seg_node =
true;
5089 if (!found_first_old_seg_node && found_last_old_seg_node)
5094 if (found_first_old_seg_node && found_last_old_seg_node)
5100 Boundary_segment_inverted[b][is] = old_inverted_segment;
5104 Boundary_segment_inverted[b][is] = !old_inverted_segment;
5108 done_segment[is] =
true;
5111 re_assigned_segments++;
5120 if ((found_first_old_seg_node && !found_last_old_seg_node) ||
5121 (!found_first_old_seg_node && found_last_old_seg_node))
5123 std::stringstream error_message;
5125 <<
"Working with boundary (" << b <<
").\nOnly the first node or "
5126 <<
"the last node of the old segment (" << old_is <<
") was\n"
5127 <<
"found. Both, first and last node should have been found in "
5128 <<
"the same segment!!!.\n"
5129 <<
"Found first seg node:" << found_first_old_seg_node <<
"\n"
5130 <<
"Found last seg node:" << found_last_old_seg_node <<
"\n\n";
5132 "TriangleMesh::re_assign_initial_zeta_values_"
5133 "for_internal_boundary()",
5134 OOMPH_EXCEPTION_LOCATION);
5147 for (
unsigned is = 0; is < nsegments; is++)
5150 if (!done_segment[is])
5153 FiniteElement* first_seg_ele_pt = segment_sorted_ele_pt[is].front();
5155 const unsigned nnod = first_seg_ele_pt->
nnode();
5157 Node* first_seg_node_pt = first_seg_ele_pt->
node_pt(0);
5158 if (is_inverted[first_seg_ele_pt])
5160 first_seg_node_pt = first_seg_ele_pt->
node_pt(nnod - 1);
5164 const double segment_first_node_zeta =
5165 sorted_segment_node_arclength[is][0];
5169 for (
unsigned i = 0;
i < 2;
i++)
5171 first_node_coord[
i] = first_seg_node_pt->x(
i);
5175 FiniteElement* last_seg_ele_pt = segment_sorted_ele_pt[is].back();
5176 Node* last_seg_node_pt = last_seg_ele_pt->
node_pt(nnod - 1);
5177 if (is_inverted[last_seg_ele_pt])
5179 last_seg_node_pt = last_seg_ele_pt->
node_pt(0);
5183 const double segment_final_node_zeta = segment_arclength[is];
5187 for (
unsigned i = 0;
i < 2;
i++)
5189 last_node_coord[
i] = last_seg_node_pt->x(
i);
5193 Boundary_segment_initial_coordinate[b][is] = first_node_coord;
5196 if (this->boundary_geom_object_pt(b) != 0)
5203 Boundary_segment_initial_zeta[b][is] = initial_zeta_segment[is];
5209 Boundary_segment_initial_arclength[b][is] = segment_first_node_zeta;
5214 Boundary_segment_final_coordinate[b][is] = last_node_coord;
5217 if (this->boundary_geom_object_pt(b) != 0)
5224 Boundary_segment_final_zeta[b][is] = final_zeta_segment[is];
5230 Boundary_segment_final_arclength[b][is] = segment_final_node_zeta;
5234 Boundary_segment_inverted[b][is] = 0;
5237 done_segment[is] =
true;
5240 re_assigned_segments++;
5248 if (re_assigned_segments != nsegments)
5250 std::stringstream error_message;
5251 error_message <<
"Working with boundary (" << b
5252 <<
").\nThe number of re-assigned "
5253 <<
"segments (" << re_assigned_segments
5254 <<
") is different from the number\nof segments ("
5255 << nsegments <<
")\n\n";
5257 error_message.str(),
5258 "TriangleMesh::re_assign_initial_zeta_values_for_internal_boundary()",
5259 OOMPH_EXCEPTION_LOCATION);
5264 for (
unsigned i = 0;
i < nele;
i++)
5266 delete face_el_pt[
i];
5280 template<
class ELEMENT>
5284 bool& is_internal_boundary,
5285 std::map<FiniteElement*, FiniteElement*>& face_to_bulk_element_pt)
5290 const unsigned my_rank = comm_pt->my_rank();
5300 const unsigned nregions = this->nregion();
5306 for (
unsigned ir = 0; ir < nregions; ir++)
5308 const unsigned region_id =
5309 static_cast<unsigned>(this->Region_attribute[ir]);
5312 const unsigned nele_in_region =
5313 this->nboundary_element_in_region(b, region_id);
5317 if (nele_in_region > 0)
5320 for (
unsigned e = 0;
e < nele_in_region;
e++)
5325 this->boundary_element_in_region_pt(b, region_id,
e);
5330 this->face_index_at_boundary_in_region(b, region_id,
e);
5337 face_to_bulk_element_pt[tmp_face_el_pt] = bulk_ele_pt;
5342 tmp_face_ele_pt.push_back(tmp_face_el_pt);
5356 const unsigned nbound_ele = this->nboundary_element(b);
5362 for (
unsigned e = 0;
e < nbound_ele;
e++)
5370 int face_index = this->face_index_at_boundary(b,
e);
5377 face_to_bulk_element_pt[tmp_face_el_pt] = bulk_ele_pt;
5382 tmp_face_ele_pt.push_back(tmp_face_el_pt);
5391 std::map<FiniteElement*, bool> done_face;
5395 is_internal_boundary =
false;
5403 const unsigned n_tmp_face_ele = tmp_face_ele_pt.size();
5404 for (
unsigned ie = 0; ie < n_tmp_face_ele; ie++)
5408 if (!done_face[main_face_ele_pt])
5411 done_face[main_face_ele_pt] =
true;
5413 const unsigned nnodes = main_face_ele_pt->
nnode();
5415 Node* main_first_node_pt = main_face_ele_pt->
node_pt(0);
5416 Node* main_last_node_pt = main_face_ele_pt->
node_pt(nnodes - 1);
5420 for (
unsigned iie = ie + 1; iie < n_tmp_face_ele; iie++)
5423 FiniteElement* dependant_face_ele_pt = tmp_face_ele_pt[iie];
5424 if (!done_face[dependant_face_ele_pt])
5428 Node* dependant_first_node_pt = dependant_face_ele_pt->
node_pt(0);
5429 Node* dependant_last_node_pt =
5430 dependant_face_ele_pt->
node_pt(nnodes - 1);
5433 if (((dependant_first_node_pt == main_first_node_pt) &&
5434 (dependant_last_node_pt == main_last_node_pt)) ||
5435 ((dependant_first_node_pt == main_last_node_pt) &&
5436 (dependant_last_node_pt == main_first_node_pt)))
5440 is_internal_boundary =
true;
5442 done_face[dependant_face_ele_pt] =
true;
5454 face_to_bulk_element_pt[main_face_ele_pt];
5456 face_to_bulk_element_pt[dependant_face_ele_pt];
5460 int processor_in_charge_main_bulk_ele =
5462 int processor_in_charge_dependant_bulk_ele =
5468 if (processor_in_charge_main_bulk_ele < 0)
5470 processor_in_charge_main_bulk_ele =
static_cast<int>(my_rank);
5472 if (processor_in_charge_dependant_bulk_ele < 0)
5474 processor_in_charge_dependant_bulk_ele =
5475 static_cast<int>(my_rank);
5480 bool add_main_face_element =
true;
5481 if (processor_in_charge_dependant_bulk_ele >
5482 processor_in_charge_main_bulk_ele)
5485 add_main_face_element =
false;
5487 else if (processor_in_charge_main_bulk_ele ==
5488 processor_in_charge_dependant_bulk_ele)
5498 const unsigned n_bulk_nodes = main_bulk_ele_pt->
nnode();
5499 for (
unsigned inode = 0; inode < n_bulk_nodes; inode++)
5501 for (
unsigned idim = 0; idim < 2; idim++)
5503 main_ele_coordinates[idim] +=
5504 main_bulk_ele_pt->
node_pt(inode)->x(idim);
5505 dependant_ele_coordinates[idim] +=
5506 dependant_bulk_ele_pt->
node_pt(inode)->x(idim);
5512 for (
unsigned idim = 0; idim < 2; idim++)
5514 main_ele_coordinates[idim] /= (double)n_bulk_nodes;
5515 dependant_ele_coordinates[idim] /= (double)n_bulk_nodes;
5521 if (dependant_ele_coordinates[1] < main_ele_coordinates[1])
5523 add_main_face_element =
false;
5525 else if (dependant_ele_coordinates[1] ==
5526 main_ele_coordinates[1])
5529 if (dependant_ele_coordinates[0] < main_ele_coordinates[0])
5531 add_main_face_element =
false;
5537 if (add_main_face_element)
5542 face_ele_pt.push_back(main_face_ele_pt);
5545 free_memory_face_ele_pt.push_back(dependant_face_ele_pt);
5552 face_ele_pt.push_back(dependant_face_ele_pt);
5555 free_memory_face_ele_pt.push_back(main_face_ele_pt);
5574 const unsigned n_free_face_ele = free_memory_face_ele_pt.size();
5575 if (n_free_face_ele == 0)
5583 face_ele_pt.resize(n_tmp_face_ele);
5585 for (
unsigned i = 0;
i < n_tmp_face_ele;
i++)
5587 face_ele_pt[
i] = tmp_face_ele_pt[
i];
5595 for (
unsigned i = 0;
i < n_free_face_ele;
i++)
5597 delete free_memory_face_ele_pt[
i];
5598 free_memory_face_ele_pt[
i] = 0;
5609 template<
class ELEMENT>
5620 const unsigned nproc = comm_pt->nproc();
5621 const unsigned my_rank = comm_pt->my_rank();
5627 const unsigned nregions = this->nregion();
5631 std::map<FiniteElement*, FiniteElement*> face_to_bulk_element_pt;
5637 for (
unsigned ir = 0; ir < nregions; ir++)
5639 const unsigned region_id =
5640 static_cast<unsigned>(this->Region_attribute[ir]);
5643 const unsigned nele_in_region =
5644 this->nboundary_element_in_region(b, region_id);
5648 if (nele_in_region > 0)
5651 for (
unsigned e = 0;
e < nele_in_region;
e++)
5655 this->boundary_element_in_region_pt(b, region_id,
e);
5659 this->face_index_at_boundary_in_region(b, region_id,
e);
5668 tmp_face_ele_pt.push_back(tmp_face_el_pt);
5670 face_to_bulk_element_pt[tmp_face_el_pt] = bulk_ele_pt;
5684 const unsigned nbound_ele = this->nboundary_element(b);
5690 for (
unsigned e = 0;
e < nbound_ele;
e++)
5696 int face_index = this->face_index_at_boundary(b,
e);
5704 tmp_face_ele_pt.push_back(tmp_face_el_pt);
5706 face_to_bulk_element_pt[tmp_face_el_pt] = bulk_ele_pt;
5720 std::map<FiniteElement*, bool> done_face;
5723 bool is_internal_boundary =
false;
5727 bool is_internal_boundary_paranoid =
false;
5731 unsigned nfound_face_elements = 0;
5735 const unsigned nbound_ele = tmp_face_ele_pt.size();
5736 for (
unsigned ie = 0; ie < nbound_ele; ie++)
5740 if (!done_face[main_face_ele_pt])
5743 done_face[main_face_ele_pt] =
true;
5745 const unsigned nnodes = main_face_ele_pt->
nnode();
5747 Node* main_first_node_pt = main_face_ele_pt->
node_pt(0);
5748 Node* main_last_node_pt = main_face_ele_pt->
node_pt(nnodes - 1);
5750 for (
unsigned iie = ie + 1; iie < nbound_ele; iie++)
5753 FiniteElement* dependant_face_ele_pt = tmp_face_ele_pt[iie];
5754 if (!done_face[dependant_face_ele_pt])
5757 Node* dependant_first_node_pt = dependant_face_ele_pt->
node_pt(0);
5758 Node* dependant_last_node_pt =
5759 dependant_face_ele_pt->
node_pt(nnodes - 1);
5762 if (((dependant_first_node_pt == main_first_node_pt) &&
5763 (dependant_last_node_pt == main_last_node_pt)) ||
5764 ((dependant_first_node_pt == main_last_node_pt) &&
5765 (dependant_last_node_pt == main_first_node_pt)))
5769 nfound_face_elements += 2;
5773 is_internal_boundary =
true;
5775 done_face[dependant_face_ele_pt] =
true;
5785 face_to_bulk_element_pt[main_face_ele_pt];
5787 face_to_bulk_element_pt[dependant_face_ele_pt];
5790 int processor_in_charge_main_bulk_ele =
5792 int processor_in_charge_dependant_bulk_ele =
5798 if (processor_in_charge_main_bulk_ele < 0)
5800 processor_in_charge_main_bulk_ele =
static_cast<int>(my_rank);
5802 if (processor_in_charge_dependant_bulk_ele < 0)
5804 processor_in_charge_dependant_bulk_ele =
5805 static_cast<int>(my_rank);
5809 bool add_main_face_element =
true;
5810 if (processor_in_charge_dependant_bulk_ele >
5811 processor_in_charge_main_bulk_ele)
5814 add_main_face_element =
false;
5816 else if (processor_in_charge_main_bulk_ele ==
5817 processor_in_charge_dependant_bulk_ele)
5825 const unsigned n_bulk_nodes = main_bulk_ele_pt->
nnode();
5826 for (
unsigned inode = 0; inode < n_bulk_nodes; inode++)
5828 for (
unsigned idim = 0; idim < 2; idim++)
5830 main_ele_coordinates[idim] +=
5831 main_bulk_ele_pt->
node_pt(inode)->x(idim);
5832 dependant_ele_coordinates[idim] +=
5833 dependant_bulk_ele_pt->
node_pt(inode)->x(idim);
5838 for (
unsigned idim = 0; idim < 2; idim++)
5840 main_ele_coordinates[idim] /= (double)n_bulk_nodes;
5841 dependant_ele_coordinates[idim] /= (double)n_bulk_nodes;
5847 if (dependant_ele_coordinates[1] < main_ele_coordinates[1])
5849 add_main_face_element =
false;
5851 else if (dependant_ele_coordinates[1] ==
5852 main_ele_coordinates[1])
5855 if (dependant_ele_coordinates[0] < main_ele_coordinates[0])
5857 add_main_face_element =
false;
5863 if (add_main_face_element)
5867 face_ele_pt.push_back(main_face_ele_pt);
5873 face_ele_pt.push_back(dependant_face_ele_pt);
5886 const unsigned nface_ele = face_ele_pt.size();
5892 if (nbound_ele > 0 && nfound_face_elements == nbound_ele)
5894 is_internal_boundary_paranoid =
true;
5897 if (nbound_ele > 0 && is_internal_boundary_paranoid &&
5898 nbound_ele != nface_ele * 2)
5900 std::ostringstream error_message;
5902 <<
"The info. to perform the synchronisation of the boundary "
5903 <<
"coordinates was not completely established\n"
5904 <<
"In this case it was the number of non repeated boundary elements\n"
5905 <<
"Number of boundary elements: (" << nbound_ele <<
")\n"
5906 <<
"Number of nonrepeated boundary elements: (" << nface_ele <<
")\n";
5908 "TriangleMesh::synchronize_boundary_coordinates()",
5909 OOMPH_EXCEPTION_LOCATION);
5919 std::vector<bool> is_halo_face_element(nface_ele,
false);
5922 unsigned nnon_halo_face_elements = 0;
5924 for (
unsigned ie = 0; ie < nface_ele; ie++)
5928 FiniteElement* tmp_bulk_ele_pt = face_to_bulk_element_pt[face_el_pt];
5930 if (!tmp_bulk_ele_pt->
is_halo())
5932 is_halo_face_element[ie] =
false;
5933 nnon_halo_face_elements++;
5938 is_halo_face_element[ie] =
true;
5951 std::map<Node*, bool> done_node;
5971 std::map<Node*, bool> done_haloed_face_node;
5974 for (
unsigned iface = 0; iface < nface_ele; iface++)
5977 if (!is_halo_face_element[iface])
5982 const unsigned nnodes = ele_face_pt->
nnode();
5984 for (
unsigned in = 0; in < nnodes; in++)
5986 Node* face_node_pt = ele_face_pt->
node_pt(in);
5988 if (!done_node[face_node_pt])
5991 done_node[face_node_pt] =
true;
5993 if (face_node_pt->is_halo())
5996 int int_nonhalo_ID = face_node_pt->non_halo_proc_ID();
5998 if (int_nonhalo_ID < 0)
6000 std::ostringstream error_message;
6002 <<
"The node was marked to be halo but the processor in "
6003 <<
"charge was found to be -1\n\n";
6005 error_message.str(),
6006 "TriangleMesh::synchronize_boundary_coordinates()",
6007 OOMPH_EXCEPTION_LOCATION);
6010 const unsigned ip =
static_cast<unsigned>(int_nonhalo_ID);
6014 face_halo_node_pt[ip].push_back(face_node_pt);
6018 bool found_halo_node =
false;
6020 const unsigned nhalo_iproc = this->nhalo_node(ip);
6021 for (
unsigned ihn = 0; ihn < nhalo_iproc; ihn++)
6023 Node* compare_face_node_pt = this->halo_node_pt(ip, ihn);
6024 if (compare_face_node_pt == face_node_pt)
6028 face_halo_node_id[ip].push_back(ihn);
6031 found_halo_node =
true;
6038 if (!found_halo_node)
6040 std::ostringstream error_message;
6042 <<
"The halo id of the current node: (" << face_node_pt->x(0)
6043 <<
", " << face_node_pt->x(1) <<
") with processor (" << ip
6044 <<
") was not found!!!\n\n";
6046 error_message.str(),
6047 "TriangleMesh::synchronize_boundary_coordinates()",
6048 OOMPH_EXCEPTION_LOCATION);
6058 for (
unsigned ip = 0; ip < nproc; ip++)
6070 const unsigned nhaloed_iproc = this->nhaloed_node(ip);
6071 for (
unsigned ihdn = 0; ihdn < nhaloed_iproc; ihdn++)
6073 Node* compare_face_node_pt = this->haloed_node_pt(ip, ihdn);
6074 if (face_node_pt == compare_face_node_pt)
6078 face_haloed_node_pt[ip].push_back(face_node_pt);
6081 face_haloed_node_id[ip].push_back(ihdn);
6085 done_haloed_face_node[face_node_pt] =
true;
6111 for (
unsigned ip = 0; ip < nproc; ip++)
6116 const unsigned nhalo_face_nodes = face_halo_node_pt[ip].size();
6118 if (nhalo_face_nodes != face_halo_node_id[ip].size())
6120 std::ostringstream error_message;
6122 <<
"The number of found halo face nodes (" << nhalo_face_nodes
6123 <<
") is different from the number of\nfound halo face ids ("
6124 << face_halo_node_id[ip].size() <<
")!!!\n\n";
6126 error_message.str(),
6127 "TriangleMesh::synchronize_boundary_coordinates()",
6128 OOMPH_EXCEPTION_LOCATION);
6138 for (
unsigned ihfn = 0; ihfn < nhalo_face_nodes; ihfn++)
6141 Node* halo_face_node_pt = face_halo_node_pt[ip][ihfn];
6143 const unsigned halo_id = face_halo_node_id[ip][ihfn];
6146 halo_face_node_pt->get_coordinates_on_boundary(b, zeta);
6148 flat_unsigned_send_packed_data.push_back(halo_id);
6149 flat_double_send_packed_data.push_back(zeta[0]);
6154 MPI_Request request;
6157 int send_proc =
static_cast<int>(ip);
6159 int receive_proc =
static_cast<int>(ip);
6167 unsigned nflat_unsigned_send = flat_unsigned_send_packed_data.size();
6168 MPI_Isend(&nflat_unsigned_send,
6173 comm_pt->mpi_comm(),
6176 unsigned nflat_unsigned_receive = 0;
6177 MPI_Recv(&nflat_unsigned_receive,
6182 comm_pt->mpi_comm(),
6185 MPI_Wait(&request, MPI_STATUS_IGNORE);
6187 if (nflat_unsigned_send != 0)
6189 MPI_Isend(&flat_unsigned_send_packed_data[0],
6190 nflat_unsigned_send,
6194 comm_pt->mpi_comm(),
6198 if (nflat_unsigned_receive != 0)
6200 flat_unsigned_receive_packed_data.resize(nflat_unsigned_receive);
6201 MPI_Recv(&flat_unsigned_receive_packed_data[0],
6202 nflat_unsigned_receive,
6206 comm_pt->mpi_comm(),
6210 if (nflat_unsigned_send != 0)
6212 MPI_Wait(&request, MPI_STATUS_IGNORE);
6217 unsigned nflat_double_send = flat_double_send_packed_data.size();
6218 MPI_Isend(&nflat_double_send,
6223 comm_pt->mpi_comm(),
6226 unsigned nflat_double_receive = 0;
6227 MPI_Recv(&nflat_double_receive,
6232 comm_pt->mpi_comm(),
6235 MPI_Wait(&request, MPI_STATUS_IGNORE);
6237 if (nflat_double_send != 0)
6239 MPI_Isend(&flat_double_send_packed_data[0],
6244 comm_pt->mpi_comm(),
6248 if (nflat_double_receive != 0)
6250 flat_double_receive_packed_data.resize(nflat_double_receive);
6251 MPI_Recv(&flat_double_receive_packed_data[0],
6252 nflat_double_receive,
6256 comm_pt->mpi_comm(),
6260 if (nflat_double_send != 0)
6262 MPI_Wait(&request, MPI_STATUS_IGNORE);
6267 if (nflat_unsigned_receive != nflat_double_receive)
6269 std::ostringstream error_message;
6270 error_message <<
"The number of unsigned received data ("
6271 << nflat_unsigned_receive <<
") is different from the "
6272 <<
"number\nof double received data ("
6273 << nflat_double_receive <<
")!!!\n\n";
6275 error_message.str(),
6276 "TriangleMesh::synchronize_boundary_coordinates()",
6277 OOMPH_EXCEPTION_LOCATION);
6284 for (
unsigned iflat_packed = 0; iflat_packed < nflat_unsigned_receive;
6288 const unsigned haloed_id =
6289 flat_unsigned_receive_packed_data[iflat_packed];
6292 zeta[0] = flat_double_receive_packed_data[iflat_packed];
6295 Node* haloed_face_node_pt = this->haloed_node_pt(ip, haloed_id);
6309 if (!done_haloed_face_node[haloed_face_node_pt])
6312 haloed_face_node_pt->set_coordinates_on_boundary(b, zeta);
6315 for (
unsigned iiproc = 0; iiproc < nproc; iiproc++)
6318 if (iiproc != my_rank)
6321 const unsigned nhaloed_node_iiproc = this->nhaloed_node(iiproc);
6322 for (
unsigned ihdn = 0; ihdn < nhaloed_node_iiproc; ihdn++)
6324 Node* compare_haloed_node_pt =
6325 this->haloed_node_pt(iiproc, ihdn);
6326 if (haloed_face_node_pt == compare_haloed_node_pt)
6330 face_haloed_node_pt[iiproc].push_back(haloed_face_node_pt);
6333 face_haloed_node_id[iiproc].push_back(ihdn);
6354 for (
unsigned ip = 0; ip < nproc; ip++)
6366 const unsigned nhaloed_face_nodes = face_haloed_node_pt[ip].size();
6368 for (
unsigned ihdfn = 0; ihdfn < nhaloed_face_nodes; ihdfn++)
6371 Node* haloed_face_node_pt = face_haloed_node_pt[ip][ihdfn];
6373 const unsigned haloed_id = face_haloed_node_id[ip][ihdfn];
6376 haloed_face_node_pt->get_coordinates_on_boundary(b, zeta);
6378 flat_unsigned_send_packed_data.push_back(haloed_id);
6379 flat_double_send_packed_data.push_back(zeta[0]);
6384 MPI_Request request;
6387 int send_proc =
static_cast<int>(ip);
6389 int receive_proc =
static_cast<int>(ip);
6397 unsigned nflat_unsigned_send = flat_unsigned_send_packed_data.size();
6398 MPI_Isend(&nflat_unsigned_send,
6403 comm_pt->mpi_comm(),
6406 unsigned nflat_unsigned_receive = 0;
6407 MPI_Recv(&nflat_unsigned_receive,
6412 comm_pt->mpi_comm(),
6415 MPI_Wait(&request, MPI_STATUS_IGNORE);
6417 if (nflat_unsigned_send != 0)
6419 MPI_Isend(&flat_unsigned_send_packed_data[0],
6420 nflat_unsigned_send,
6424 comm_pt->mpi_comm(),
6428 if (nflat_unsigned_receive != 0)
6430 flat_unsigned_receive_packed_data.resize(nflat_unsigned_receive);
6431 MPI_Recv(&flat_unsigned_receive_packed_data[0],
6432 nflat_unsigned_receive,
6436 comm_pt->mpi_comm(),
6440 if (nflat_unsigned_send != 0)
6442 MPI_Wait(&request, MPI_STATUS_IGNORE);
6447 unsigned nflat_double_send = flat_double_send_packed_data.size();
6448 MPI_Isend(&nflat_double_send,
6453 comm_pt->mpi_comm(),
6456 unsigned nflat_double_receive = 0;
6457 MPI_Recv(&nflat_double_receive,
6462 comm_pt->mpi_comm(),
6465 MPI_Wait(&request, MPI_STATUS_IGNORE);
6467 if (nflat_double_send != 0)
6469 MPI_Isend(&flat_double_send_packed_data[0],
6474 comm_pt->mpi_comm(),
6478 if (nflat_double_receive != 0)
6480 flat_double_receive_packed_data.resize(nflat_double_receive);
6481 MPI_Recv(&flat_double_receive_packed_data[0],
6482 nflat_double_receive,
6486 comm_pt->mpi_comm(),
6490 if (nflat_double_send != 0)
6492 MPI_Wait(&request, MPI_STATUS_IGNORE);
6497 if (nflat_unsigned_receive != nflat_double_receive)
6499 std::ostringstream error_message;
6500 error_message <<
"The number of unsigned received data ("
6501 << nflat_unsigned_receive <<
") is different from the "
6502 <<
"number\nof double received data ("
6503 << nflat_double_receive <<
")!!!\n\n";
6505 error_message.str(),
6506 "TriangleMesh::synchronize_boundary_coordinates()",
6507 OOMPH_EXCEPTION_LOCATION);
6514 for (
unsigned iflat_packed = 0; iflat_packed < nflat_unsigned_receive;
6518 const unsigned halo_id =
6519 flat_unsigned_receive_packed_data[iflat_packed];
6522 zeta[0] = flat_double_receive_packed_data[iflat_packed];
6525 Node* halo_face_node_pt = this->halo_node_pt(ip, halo_id);
6536 halo_face_node_pt->set_coordinates_on_boundary(b, zeta);
6542 for (
unsigned ie = 0; ie < nbound_ele; ie++)
6544 delete tmp_face_ele_pt[ie];
6545 tmp_face_ele_pt[ie] = 0;
6550 if (is_internal_boundary)
6552 re_scale_re_assigned_initial_zeta_values_for_internal_boundary(b);
6562 template<
class ELEMENT>
6580 unsigned n_repeated_ele = 0;
6582 const unsigned n_regions = this->nregion();
6591 for (
unsigned rr = 0; rr < n_regions; rr++)
6593 const unsigned region_id =
6594 static_cast<unsigned>(this->Region_attribute[rr]);
6597 const unsigned nel_in_region =
6598 this->nboundary_element_in_region(b, region_id);
6600 unsigned nel_repetead_in_region = 0;
6604 if (nel_in_region > 0)
6606 bool repeated =
false;
6609 for (
unsigned e = 0;
e < nel_in_region;
e++)
6614 this->boundary_element_in_region_pt(b, region_id,
e);
6625 this->face_index_at_boundary_in_region(b, region_id,
e);
6633 const unsigned n_nodes = tmp_ele_pt->
nnode();
6635 std::pair<Node*, Node*> tmp_pair = std::make_pair(
6638 std::pair<Node*, Node*> tmp_pair_inverse = std::make_pair(
6642 const unsigned n_done_nodes = done_nodes_pt.size();
6643 for (
unsigned l = 0; l < n_done_nodes; l++)
6645 if (tmp_pair == done_nodes_pt[l] ||
6646 tmp_pair_inverse == done_nodes_pt[l])
6648 nel_repetead_in_region++;
6658 done_nodes_pt.push_back(tmp_pair);
6660 face_el_pt.push_back(tmp_ele_pt);
6674 nele += nel_in_region;
6676 n_repeated_ele += nel_repetead_in_region;
6685 nele = this->nboundary_element(b);
6691 bool repeated =
false;
6694 for (
unsigned e = 0;
e < nele;
e++)
6709 int face_index = this->face_index_at_boundary(b,
e);
6717 const unsigned n_nodes = tmp_ele_pt->
nnode();
6719 std::pair<Node*, Node*> tmp_pair = std::make_pair(
6722 std::pair<Node*, Node*> tmp_pair_inverse = std::make_pair(
6726 const unsigned n_done_nodes = done_nodes_pt.size();
6727 for (
unsigned l = 0; l < n_done_nodes; l++)
6729 if (tmp_pair == done_nodes_pt[l] ||
6730 tmp_pair_inverse == done_nodes_pt[l])
6744 done_nodes_pt.push_back(tmp_pair);
6746 face_el_pt.push_back(tmp_ele_pt);
6764 nele -= n_repeated_ele;
6767 if (nele != face_el_pt.size())
6769 std::ostringstream error_message;
6771 <<
"The independet counting of face elements (" << nele <<
") for "
6772 <<
"boundary (" << b <<
") is different\n"
6773 <<
"from the real number of face elements in the container ("
6774 << face_el_pt.size() <<
")\n";
6777 "TriangleMesh::re_scale_re_assigned_initial_zeta_"
6778 "values_for_internal_boundary()",
6779 OOMPH_EXCEPTION_LOCATION);
6789 const unsigned nnon_halo_face_elements = face_el_pt.size();
6796 unsigned nsorted_face_elements = 0;
6799 std::map<FiniteElement*, bool> done_el;
6802 std::map<FiniteElement*, bool> is_inverted;
6805 while (nsorted_face_elements < nnon_halo_face_elements)
6809 std::list<FiniteElement*> sorted_el_pt;
6813 bool found_initial_face_element =
false;
6819 for (iface = 0; iface < nele; iface++)
6821 ele_face_pt = face_el_pt[iface];
6823 if (!done_el[ele_face_pt])
6826 found_initial_face_element =
true;
6828 nsorted_face_elements++;
6830 sorted_el_pt.push_back(ele_face_pt);
6832 done_el[ele_face_pt] =
true;
6838 if (!found_initial_face_element)
6840 std::ostringstream error_message;
6842 <<
"Could not find an initial face element for the current segment\n";
6845 "TriangleMesh::re_scale_re_assigned_initial_zeta_"
6846 "values_for_internal_boundary()",
6847 OOMPH_EXCEPTION_LOCATION);
6852 const unsigned nnod = ele_face_pt->
nnode();
6856 Node* left_node_pt = ele_face_pt->
node_pt(0);
6857 Node* right_node_pt = ele_face_pt->
node_pt(nnod - 1);
6861 bool face_element_added =
false;
6870 for (
unsigned iiface = iface; iiface < nele; iiface++)
6873 face_element_added =
false;
6876 ele_face_pt = face_el_pt[iiface];
6879 if (!(done_el[ele_face_pt]))
6882 Node* local_left_node_pt = ele_face_pt->node_pt(0);
6883 Node* local_right_node_pt = ele_face_pt->node_pt(nnod - 1);
6886 if (left_node_pt == local_right_node_pt)
6888 left_node_pt = local_left_node_pt;
6889 sorted_el_pt.push_front(ele_face_pt);
6890 is_inverted[ele_face_pt] =
false;
6891 face_element_added =
true;
6894 else if (left_node_pt == local_left_node_pt)
6896 left_node_pt = local_right_node_pt;
6897 sorted_el_pt.push_front(ele_face_pt);
6898 is_inverted[ele_face_pt] =
true;
6899 face_element_added =
true;
6902 else if (right_node_pt == local_left_node_pt)
6904 right_node_pt = local_right_node_pt;
6905 sorted_el_pt.push_back(ele_face_pt);
6906 is_inverted[ele_face_pt] =
false;
6907 face_element_added =
true;
6910 else if (right_node_pt == local_right_node_pt)
6912 right_node_pt = local_left_node_pt;
6913 sorted_el_pt.push_back(ele_face_pt);
6914 is_inverted[ele_face_pt] =
true;
6915 face_element_added =
true;
6918 if (face_element_added)
6920 done_el[ele_face_pt] =
true;
6921 nsorted_face_elements++;
6927 }
while (face_element_added &&
6928 (nsorted_face_elements < nnon_halo_face_elements));
6931 segment_sorted_ele_pt.push_back(sorted_el_pt);
6947 const unsigned nsegments = segment_sorted_ele_pt.size();
6950 if (nnon_halo_face_elements > 0 && nsegments == 0)
6952 std::ostringstream error_message;
6954 <<
"The number of segments is zero, but the number of nonhalo\n"
6955 <<
"elements is: (" << nnon_halo_face_elements <<
")\n";
6957 "TriangleMesh::re_scale_re_assigned_initial_zeta_"
6958 "values_for_internal_boundary()",
6959 OOMPH_EXCEPTION_LOCATION);
6974 for (
unsigned is = 0; is < nsegments; is++)
6977 if (segment_sorted_ele_pt[is].size() == 0)
6979 std::ostringstream error_message;
6980 error_message <<
"The (" << is <<
")-th segment has no elements\n";
6982 "TriangleMesh::re_scale_re_assigned_initial_zeta_"
6983 "values_for_internal_boundary()",
6984 OOMPH_EXCEPTION_LOCATION);
6989 FiniteElement* first_ele_pt = segment_sorted_ele_pt[is].front();
6992 const unsigned nnod = first_ele_pt->
nnode();
6995 Node* first_node_pt = first_ele_pt->
node_pt(0);
6996 if (is_inverted[first_ele_pt])
6998 first_node_pt = first_ele_pt->
node_pt(nnod - 1);
7002 FiniteElement* last_ele_pt = segment_sorted_ele_pt[is].back();
7005 Node* last_node_pt = last_ele_pt->
node_pt(nnod - 1);
7006 if (is_inverted[last_ele_pt])
7008 last_node_pt = last_ele_pt->
node_pt(0);
7012 double x_left = first_node_pt->x(0);
7013 double y_left = first_node_pt->x(1);
7022 if (this->boundary_geom_object_pt(b) != 0)
7024 first_node_pt->get_coordinates_on_boundary(b, zeta);
7025 initial_zeta_segment[is] = zeta[0];
7026 last_node_pt->get_coordinates_on_boundary(b, zeta);
7027 final_zeta_segment[is] = zeta[0];
7031 std::set<Node*> local_nodes_pt;
7032 local_nodes_pt.insert(first_node_pt);
7035 for (std::list<FiniteElement*>::iterator it =
7036 segment_sorted_ele_pt[is].begin();
7037 it != segment_sorted_ele_pt[is].end();
7046 if (is_inverted[el_pt])
7053 for (
unsigned j = 1; j < nnod; j++)
7055 Node* nod_pt = el_pt->
node_pt(k_nod);
7059 double x_right = nod_pt->x(0);
7060 double y_right = nod_pt->x(1);
7063 zeta[0] += sqrt((x_right - x_left) * (x_right - x_left) +
7064 (y_right - y_left) * (y_right - y_left));
7072 local_nodes_pt.insert(nod_pt);
7078 segment_arclength[is] = zeta[0];
7081 segment_all_nodes_pt.push_back(local_nodes_pt);
7093 Boundary_segment_inverted[b].clear();
7094 Boundary_segment_initial_coordinate[b].clear();
7095 Boundary_segment_final_coordinate[b].clear();
7097 Boundary_segment_initial_zeta[b].clear();
7098 Boundary_segment_final_zeta[b].clear();
7100 Boundary_segment_initial_arclength[b].clear();
7101 Boundary_segment_final_arclength[b].clear();
7106 first_node_zeta_coordinate = boundary_initial_zeta_coordinate(b);
7107 last_node_zeta_coordinate = boundary_final_zeta_coordinate(b);
7110 const double boundary_arclength =
7111 std::max(first_node_zeta_coordinate[0], last_node_zeta_coordinate[0]);
7115 for (
unsigned is = 0; is < nsegments; is++)
7118 FiniteElement* first_face_ele_pt = segment_sorted_ele_pt[is].front();
7121 const unsigned nnod = first_face_ele_pt->
nnode();
7124 Node* first_node_pt = first_face_ele_pt->
node_pt(0);
7125 if (is_inverted[first_face_ele_pt])
7127 first_node_pt = first_face_ele_pt->
node_pt(nnod - 1);
7132 first_node_pt->get_coordinates_on_boundary(b, zeta_first);
7135 FiniteElement* last_face_ele_pt = segment_sorted_ele_pt[is].back();
7138 Node* last_node_pt = last_face_ele_pt->
node_pt(nnod - 1);
7139 if (is_inverted[last_face_ele_pt])
7141 last_node_pt = last_face_ele_pt->
node_pt(0);
7146 last_node_pt->get_coordinates_on_boundary(b, zeta_last);
7152 for (
unsigned i = 0;
i < 2;
i++)
7154 first_node_coord[
i] = first_node_pt->x(
i);
7155 last_node_coord[
i] = last_node_pt->x(
i);
7159 Boundary_segment_inverted[b].push_back(0);
7160 Boundary_segment_initial_coordinate[b].push_back(first_node_coord);
7161 Boundary_segment_final_coordinate[b].push_back(last_node_coord);
7164 if (this->boundary_geom_object_pt(b) != 0)
7166 Boundary_segment_initial_zeta[b].push_back(zeta_first[0]);
7167 Boundary_segment_final_zeta[b].push_back(zeta_last[0]);
7172 Boundary_segment_initial_arclength[b].push_back(zeta_first[0] *
7173 boundary_arclength);
7174 Boundary_segment_final_arclength[b].push_back(zeta_last[0] *
7175 boundary_arclength);
7181 for (
unsigned i = 0;
i < nele;
i++)
7183 delete face_el_pt[
i];
7191#ifdef OOMPH_HAS_TRIANGLE_LIB
7196 template<
class ELEMENT>
7200 bool& use_attributes)
7204 std::ifstream poly_file(poly_file_name.c_str(), std::ios_base::in);
7208 OOMPH_CURRENT_FUNCTION,
7209 OOMPH_EXCEPTION_LOCATION);
7216 poly_file.ignore(80,
'\n');
7219 unsigned invertices;
7220 poly_file >> invertices;
7225 (
double*)malloc(triangulate_io.
numberofpoints * 2 *
sizeof(
double));
7229 poly_file >> mesh_dim;
7240 OOMPH_CURRENT_FUNCTION,
7241 OOMPH_EXCEPTION_LOCATION);
7247 poly_file >> nextras;
7253 unsigned nodemarkers;
7254 poly_file >> nodemarkers;
7260 if (nextras != 0 || nodemarkers != 0)
7262 oomph_info <<
"===================================================="
7265 oomph_info <<
"Reading the .poly file via oomph_lib \n"
7266 <<
"point's attribute and point's markers \n"
7267 <<
"are automatically set to 0" << std::endl;
7268 oomph_info <<
"===================================================="
7274 unsigned dummy_value;
7275 unsigned count_point = 0;
7279 getline(poly_file, test_string,
'#');
7280 poly_file.ignore(80,
'\n');
7284 for (
unsigned count = 0; count < invertices; count++)
7286 poly_file >> dummy_value;
7287 poly_file >> triangulate_io.
pointlist[count_point];
7288 poly_file >> triangulate_io.
pointlist[count_point + 1];
7289 if (nextras != 0 || nodemarkers != 0)
7291 for (
unsigned j = 0; j < nextras; j++)
7293 poly_file >> dummy_value;
7296 else if (nextras != 0 && nodemarkers != 0)
7298 for (
unsigned j = 0; j < nextras; j++)
7300 poly_file >> dummy_value;
7301 poly_file >> dummy_value;
7305 poly_file.ignore(80,
'\n');
7308 if (poly_file.get() ==
'#')
7310 poly_file.ignore(80,
'\n');
7326 unsigned inelements;
7327 poly_file >> inelements;
7329 unsigned segment_markers;
7330 poly_file >> segment_markers;
7335 if (segment_markers != 1)
7337 std::ostringstream error_stream;
7338 error_stream <<
"The segment marker should be provided \n"
7339 <<
"In order to assign each segment to a boundary \n "
7343 error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
7354 for (
unsigned i = 0;
i < 2 * inelements;
i += 2)
7356 poly_file >> dummy_seg;
7359 if (segment_markers != 0)
7365 poly_file.ignore(80,
'\n');
7370 if (getline(poly_file, test_string,
'#'))
7372 poly_file.ignore(80,
'\n');
7374 unsigned dummy_hole;
7380 (
double*)malloc(triangulate_io.
numberofholes * 2 *
sizeof(
double));
7384 for (
unsigned i = 0;
i < 2 * nhole;
i += 2)
7386 poly_file >> dummy_hole;
7387 poly_file >> triangulate_io.
holelist[
i];
7388 poly_file >> triangulate_io.
holelist[
i + 1];
7394 if (getline(poly_file, test_string,
'#'))
7396 poly_file.ignore(80,
'\n');
7398 unsigned dummy_region;
7400 poly_file >> nregion;
7401 std::cerr <<
"Regions: " << nregion << std::endl;
7411 use_attributes =
true;
7416 for (
unsigned i = 0;
i < nregion;
i++)
7418 poly_file >> dummy_region;
7420 poly_file >> triangulate_io.
regionlist[4 *
i + 1];
7421 poly_file >> triangulate_io.
regionlist[4 *
i + 2];
7429#ifdef OOMPH_HAS_TRIANGLE_LIB
7435 template<
class ELEMENT>
7437 std::ostream& dump_file)
7440 if (this->is_mesh_distributed())
7443 const unsigned nboundary = this->nboundary();
7444 dump_file << nboundary <<
" # number of original boundaries" << std::endl;
7447 const unsigned nshared_boundaries = this->nshared_boundaries();
7448 dump_file << nshared_boundaries <<
" # number of shared boundaries"
7452 const unsigned init_shd_bnd_id = this->initial_shared_boundary_id();
7453 dump_file << init_shd_bnd_id <<
" # initial shared boundaries id"
7456 const unsigned final_shd_bnd_id = this->final_shared_boundary_id();
7457 dump_file << final_shd_bnd_id <<
" # final shared boundaries id"
7461 const unsigned nprocs = this->shared_boundaries_ids().size();
7462 dump_file << nprocs <<
" # number of processors" << std::endl;
7466 for (
unsigned ip = 0; ip < nprocs; ip++)
7468 for (
unsigned jp = 0; jp < nprocs; jp++)
7474 const unsigned nshared_boundaries_iproc_jproc =
7475 this->shared_boundaries_ids(ip, jp).size();
7479 dump_file << nshared_boundaries_iproc_jproc
7480 <<
" # number of shared boundaries with in two "
7481 <<
"processors" << std::endl;
7482 for (
unsigned is = 0; is < nshared_boundaries_iproc_jproc; is++)
7484 const unsigned shared_boundary_id =
7485 this->shared_boundaries_ids(ip, jp, is);
7486 dump_file << ip <<
" " << jp <<
" " << shared_boundary_id
7487 <<
" # ip jp shared_boundary of processors ip and jp"
7500 const unsigned nshared_boundaries_overlap_internal_boundaries =
7501 this->nshared_boundary_overlaps_internal_boundary();
7502 dump_file << nshared_boundaries_overlap_internal_boundaries
7503 <<
" # number of shared boundaries that overlap internal "
7504 <<
"boundaries" << std::endl;
7506 if (nshared_boundaries_overlap_internal_boundaries > 0)
7508 for (
unsigned isb = init_shd_bnd_id; isb < final_shd_bnd_id; isb++)
7512 if (this->shared_boundary_overlaps_internal_boundary(isb))
7516 const unsigned overlapped_internal_boundary =
7517 shared_boundary_overlapping_internal_boundary(isb);
7519 dump_file << isb <<
" " << overlapped_internal_boundary
7520 <<
" # the shared boundary overlaps the internal "
7521 <<
"boundary " << std::endl;
7532 for (
unsigned b = 0; b < nboundary; b++)
7537 if (Assigned_segments_initial_zeta_values[b])
7541 dump_file <<
"1 # assigned boundary coordinates initial zeta values"
7549 this->boundary_initial_coordinate(b);
7551 Vector<double> final_coordinates = this->boundary_final_coordinate(b);
7553 dump_file << std::setprecision(14) << initial_coordinates[0] <<
" "
7554 << initial_coordinates[1]
7555 <<
" # initial coordinates for the current boundary"
7558 dump_file << std::setprecision(14) << final_coordinates[0] <<
" "
7559 << final_coordinates[1]
7560 <<
" # final coordinates for the current boundary"
7567 const unsigned zeta_size =
7568 this->boundary_initial_zeta_coordinate(b).size();
7572 std::ostringstream error_message;
7574 <<
"The dimension for the zeta values container is different\n"
7575 <<
"from 1, the current implementation only supports\n"
7576 <<
"one-dimensioned zeta containers\n\n";
7578 error_message.str(),
7579 "TriangleMesh::dump_distributed_info_for_restart()",
7580 OOMPH_EXCEPTION_LOCATION);
7585 this->boundary_initial_zeta_coordinate(b);
7586 Vector<double> zeta_final = this->boundary_final_zeta_coordinate(b);
7588 dump_file << std::setprecision(14) << zeta_initial[0]
7589 <<
" # initial zeta value for the current boundary"
7592 dump_file << std::setprecision(14) << zeta_final[0]
7593 <<
" # final zeta value for the current boundary"
7597 const unsigned nsegments = this->nboundary_segment(b);
7599 dump_file << b <<
" " << nsegments
7600 <<
" # of segments for the current boundary" << std::endl;
7603 for (
unsigned is = 0; is < nsegments; is++)
7607 this->boundary_segment_initial_coordinate(b)[is];
7609 this->boundary_segment_final_coordinate(b)[is];
7612 << std::setprecision(14) << initial_segment_coordinates[0] <<
" "
7613 << initial_segment_coordinates[1]
7614 <<
" # initial segment coordinates for the current boundary"
7617 dump_file << std::setprecision(14) << final_segment_coordinates[0]
7618 <<
" " << final_segment_coordinates[1]
7619 <<
" # final segment coordinates for the current boundary"
7624 if (this->boundary_geom_object_pt(b) != 0)
7626 const double zeta_segment_initial =
7627 this->boundary_segment_initial_zeta(b)[is];
7628 const double zeta_segment_final =
7629 this->boundary_segment_final_zeta(b)[is];
7632 << std::setprecision(14) << zeta_segment_initial
7633 <<
" # initial segment zeta value for the current boundary"
7637 << std::setprecision(14) << zeta_segment_final
7638 <<
" # final segment zeta value for the current boundary"
7643 const double arclength_segment_initial =
7644 this->boundary_segment_initial_arclength(b)[is];
7645 const double arclength_segment_final =
7646 this->boundary_segment_final_arclength(b)[is];
7649 << std::setprecision(14) << arclength_segment_initial
7650 <<
" # initial segment arclength for the current boundary"
7653 dump_file << std::setprecision(14) << arclength_segment_final
7654 <<
" # final segment arclength for the current boundary"
7666 dump_file <<
"0 # assigned boundary coordinates initial zeta values"
7678 template<
class ELEMENT>
7680 std::istream& restart_file)
7683 if (this->is_mesh_distributed())
7686 const unsigned n_boundary = read_unsigned_line_helper(restart_file);
7689 if (n_boundary != this->nboundary())
7691 std::ostringstream error_message;
7693 <<
"The number of boundaries (" << n_boundary <<
") on the "
7694 <<
"file used for restarting is different\nfrom the number of "
7695 <<
"boundaries (" << this->nboundary() <<
") on the current "
7698 "TriangleMesh::read_distributed_info_for_restart()",
7699 OOMPH_EXCEPTION_LOCATION);
7704 unsigned n_shared_boundaries = read_unsigned_line_helper(restart_file);
7707 n_shared_boundaries++;
7708 n_shared_boundaries--;
7711 unsigned init_shd_bnd_id = read_unsigned_line_helper(restart_file);
7717 unsigned final_shd_bnd_id = read_unsigned_line_helper(restart_file);
7725 const unsigned n_procs = read_unsigned_line_helper(restart_file);
7728 if (
static_cast<int>(n_procs) != this->communicator_pt()->nproc())
7730 std::ostringstream error_message;
7732 <<
"The number of previously used processors (" << n_procs
7733 <<
") (read from the restart file) is different\nfrom the "
7734 <<
"number of current used processors ("
7735 << this->communicator_pt()->nproc() <<
")\n\n";
7737 "TriangleMesh::read_distributed_info_for_restart()",
7738 OOMPH_EXCEPTION_LOCATION);
7743 this->shared_boundaries_ids().clear();
7744 this->shared_boundary_from_processors().clear();
7745 this->shared_boundary_overlaps_internal_boundary().clear();
7749 this->shared_boundaries_ids().resize(n_procs);
7753 for (
unsigned ip = 0; ip < n_procs; ip++)
7757 this->shared_boundaries_ids(ip).resize(n_procs);
7758 for (
unsigned jp = 0; jp < n_procs; jp++)
7764 const unsigned nshared_boundaries_iproc_jproc =
7765 read_unsigned_line_helper(restart_file);
7766 for (
unsigned is = 0; is < nshared_boundaries_iproc_jproc; is++)
7770 restart_file >> tmp_ip;
7772 restart_file >> tmp_jp;
7776 const unsigned shared_boundary_id =
7777 read_unsigned_line_helper(restart_file);
7781 this->shared_boundaries_ids(ip, jp).push_back(shared_boundary_id);
7788 this->shared_boundary_from_processors()[shared_boundary_id] =
7801 const unsigned nshared_boundaries_overlap_internal_boundaries =
7802 read_unsigned_line_helper(restart_file);
7804 for (
unsigned isb = 0;
7805 isb < nshared_boundaries_overlap_internal_boundaries;
7809 unsigned shared_boundary_overlapping;
7810 restart_file >> shared_boundary_overlapping;
7812 const unsigned overlapped_internal_boundary =
7813 read_unsigned_line_helper(restart_file);
7817 this->shared_boundary_overlaps_internal_boundary()
7818 [shared_boundary_overlapping] = overlapped_internal_boundary;
7826 for (
unsigned b = 0; b < n_boundary; b++)
7830 const unsigned boundary_coordinates_initial_zeta_values_assigned =
7831 read_unsigned_line_helper(restart_file);
7833 if (boundary_coordinates_initial_zeta_values_assigned)
7838 Boundary_initial_coordinate[b].clear();
7839 Boundary_final_coordinate[b].clear();
7841 Boundary_initial_zeta_coordinate[b].clear();
7842 Boundary_final_zeta_coordinate[b].clear();
7845 Boundary_segment_inverted[b].clear();
7846 Boundary_segment_initial_coordinate[b].clear();
7847 Boundary_segment_final_coordinate[b].clear();
7849 Boundary_segment_initial_zeta[b].clear();
7850 Boundary_segment_final_zeta[b].clear();
7852 Boundary_segment_initial_arclength[b].clear();
7853 Boundary_segment_final_arclength[b].clear();
7862 restart_file >> initial_coordinates[0] >> initial_coordinates[1];
7865 restart_file.ignore(80,
'\n');
7870 restart_file >> final_coordinates[0] >> final_coordinates[1];
7873 restart_file.ignore(80,
'\n');
7878 this->boundary_initial_coordinate(b) = initial_coordinates;
7879 this->boundary_final_coordinate(b) = final_coordinates;
7883 restart_file >> zeta_initial[0];
7886 restart_file.ignore(80,
'\n');
7889 restart_file >> zeta_final[0];
7892 restart_file.ignore(80,
'\n');
7895 this->boundary_initial_zeta_coordinate(b) = zeta_initial;
7896 this->boundary_final_zeta_coordinate(b) = zeta_final;
7899 unsigned current_boundary;
7900 restart_file >> current_boundary;
7903 if (current_boundary != b)
7905 std::ostringstream error_message;
7907 <<
"The current boundary id from the restart file ("
7908 << current_boundary <<
") is different from\nthe boundary id "
7909 << b <<
"currently used to re-establish the initial and\nfinal "
7910 <<
"segment's zeta values\n\n";
7912 error_message.str(),
7913 "TriangleMesh::read_distributed_info_for_restart()",
7914 OOMPH_EXCEPTION_LOCATION);
7920 restart_file >> nsegments;
7923 restart_file.ignore(80,
'\n');
7928 for (
unsigned is = 0; is < nsegments; is++)
7934 restart_file >> initial_segment_coordinates[0] >>
7935 initial_segment_coordinates[1];
7938 restart_file.ignore(80,
'\n');
7943 restart_file >> final_segment_coordinates[0] >>
7944 final_segment_coordinates[1];
7947 restart_file.ignore(80,
'\n');
7950 this->boundary_segment_initial_coordinate(b).push_back(
7951 initial_segment_coordinates);
7952 this->boundary_segment_final_coordinate(b).push_back(
7953 final_segment_coordinates);
7956 if (this->boundary_geom_object_pt(b) != 0)
7959 restart_file >> zeta_segment_initial[0];
7962 restart_file.ignore(80,
'\n');
7965 restart_file >> zeta_segment_final[0];
7968 restart_file.ignore(80,
'\n');
7971 this->boundary_segment_initial_zeta(b).push_back(
7972 zeta_segment_initial[0]);
7973 this->boundary_segment_final_zeta(b).push_back(
7974 zeta_segment_final[0]);
7979 restart_file >> arclength_segment_initial[0];
7982 restart_file.ignore(80,
'\n');
7985 restart_file >> arclength_segment_final[0];
7988 restart_file.ignore(80,
'\n');
7991 this->boundary_segment_initial_arclength(b).push_back(
7992 arclength_segment_initial[0]);
7993 this->boundary_segment_final_arclength(b).push_back(
7994 arclength_segment_final[0]);
8013 template<
class ELEMENT>
8015 std::ostream& outfile)
8024 std::set<Node*> boundary_nodes_pt;
8025 const unsigned n_boundary_ele = this->nboundary_element(b);
8026 for (
unsigned e = 0;
e < n_boundary_ele;
e++)
8036 int face_index = this->face_index_at_boundary(b,
e);
8042 const unsigned n_nodes = face_ele_pt->
nnode();
8043 for (
unsigned i = 0;
i < n_nodes;
i++)
8046 Node* tmp_node_pt = face_ele_pt->
node_pt(
i);
8048 boundary_nodes_pt.insert(tmp_node_pt);
8060 outfile <<
"ZONE T=\"Boundary nodes" << b <<
"\"\n";
8062 std::set<Vector<double>> set_node_coord;
8064 for (std::set<Node*>::iterator it = boundary_nodes_pt.begin();
8065 it != boundary_nodes_pt.end();
8068 Node* inode_pt = (*it);
8071 const unsigned n_dim = inode_pt->
ndim();
8076 inode_pt->get_coordinates_on_boundary(b, zeta);
8077 node_coord[0] = zeta[0];
8078 for (
unsigned j = 0; j < n_dim; j++)
8080 node_coord[j + 1] = inode_pt->x(j);
8082 set_node_coord.insert(node_coord);
8085 for (std::set<
Vector<double>>::iterator it = set_node_coord.begin();
8086 it != set_node_coord.end();
8093 const unsigned n_dim = node_coord.size() - 1;
8094 for (
unsigned j = 0; j < n_dim; j++)
8096 outfile << node_coord[j + 1] <<
" ";
8099 outfile <<
"0.0" << std::endl;
8103 outfile <<
"ZONE T=\"Boundary coordinates " << b <<
"\"\n";
8104 for (std::set<
Vector<double>>::iterator it = set_node_coord.begin();
8105 it != set_node_coord.end();
8112 const unsigned n_dim = node_coord.size() - 1;
8113 for (
unsigned j = 0; j < n_dim; j++)
8115 outfile << node_coord[j + 1] <<
" ";
8119 outfile << node_coord[0] << std::endl;
8130 template<
class ELEMENT>
8141 const unsigned my_rank = this->communicator_pt()->my_rank();
8163 const unsigned nouter = this->Outer_boundary_pt.size();
8164 for (
unsigned i = 0;
i < nouter;
i++)
8166 const unsigned npolylines = this->Outer_boundary_pt[
i]->npolyline();
8167 for (
unsigned p = 0; p < npolylines; p++)
8171 this->Outer_boundary_pt[
i]->polyline_pt(p);
8172 const unsigned nvertex = tmp_polyline_pt->
nvertex();
8178 const unsigned bound_id = tmp_polyline_pt->
boundary_id();
8179 if (!boundary_was_splitted(bound_id))
8181 unsorted_outer_polyline_pt.push_back(tmp_polyline_pt);
8187 boundary_subpolylines(bound_id);
8188 const unsigned nsub_poly = tmp_vector_polylines.size();
8192 std::ostringstream error_message;
8193 error_message <<
"The boundary (" << bound_id
8194 <<
") was marked to be splitted but\n"
8195 <<
"there are only (" << nsub_poly
8196 <<
") polylines to represent it.\n";
8198 OOMPH_CURRENT_FUNCTION,
8199 OOMPH_EXCEPTION_LOCATION);
8204 for (
unsigned isub = 0; isub < nsub_poly; isub++)
8206 unsorted_outer_polyline_pt.push_back(tmp_vector_polylines[isub]);
8208 const unsigned nsvertex = tmp_vector_polylines[isub]->nvertex();
8211 std::ostringstream error_message;
8213 <<
"The current chunk (" << isub <<
") of the polyline with\n"
8214 <<
"boundary id (" << bound_id <<
") has no vertices\n";
8216 OOMPH_CURRENT_FUNCTION,
8217 OOMPH_EXCEPTION_LOCATION);
8227 unsigned nunsorted_outer_polyline = unsorted_outer_polyline_pt.size();
8228 if (nunsorted_outer_polyline > 0)
8232 sort_polylines_helper(unsorted_outer_polyline_pt, sorted_outer_curves_pt);
8251 const unsigned ninternal_closed = this->Internal_polygon_pt.size();
8252 for (
unsigned i = 0;
i < ninternal_closed;
i++)
8254 const unsigned npolylines = this->Internal_polygon_pt[
i]->npolyline();
8255 for (
unsigned p = 0; p < npolylines; p++)
8259 this->Internal_polygon_pt[
i]->polyline_pt(p);
8260 const unsigned nvertex = tmp_polyline_pt->
nvertex();
8266 const unsigned bound_id = tmp_polyline_pt->
boundary_id();
8267 if (!boundary_was_splitted(bound_id))
8269 unsorted_internal_closed_polyline_pt.push_back(tmp_polyline_pt);
8275 boundary_subpolylines(bound_id);
8276 const unsigned nsub_poly = tmp_vector_polylines.size();
8280 std::ostringstream error_message;
8281 error_message <<
"The boundary (" << bound_id
8282 <<
") was marked to be splitted but\n"
8283 <<
"there are only (" << nsub_poly
8284 <<
") polylines to represent it.\n";
8286 OOMPH_CURRENT_FUNCTION,
8287 OOMPH_EXCEPTION_LOCATION);
8292 for (
unsigned isub = 0; isub < nsub_poly; isub++)
8294 unsorted_internal_closed_polyline_pt.push_back(
8295 tmp_vector_polylines[isub]);
8297 const unsigned nsvertex = tmp_vector_polylines[isub]->nvertex();
8300 std::ostringstream error_message;
8302 <<
"The current chunk (" << isub <<
") of the polyline with\n"
8303 <<
"boundary id (" << bound_id <<
") has no vertices\n";
8305 OOMPH_CURRENT_FUNCTION,
8306 OOMPH_EXCEPTION_LOCATION);
8315 const unsigned nunsorted_internal_closed_polyline =
8316 unsorted_internal_closed_polyline_pt.size();
8318 if (nunsorted_internal_closed_polyline > 0)
8322 sort_polylines_helper(unsorted_internal_closed_polyline_pt,
8323 sorted_internal_closed_curves_pt);
8341 const unsigned ninternal_open = this->Internal_open_curve_pt.size();
8342 for (
unsigned i = 0;
i < ninternal_open;
i++)
8344 const unsigned ncurve_section =
8345 this->Internal_open_curve_pt[
i]->ncurve_section();
8346 for (
unsigned p = 0; p < ncurve_section; p++)
8350 this->Internal_open_curve_pt[
i]->polyline_pt(p);
8351 const unsigned nvertex = tmp_polyline_pt->
nvertex();
8357 const unsigned bound_id = tmp_polyline_pt->
boundary_id();
8358 if (!boundary_was_splitted(bound_id))
8362 if (!boundary_marked_as_shared_boundary(bound_id, 0))
8364 unsorted_internal_open_polyline_pt.push_back(tmp_polyline_pt);
8371 boundary_subpolylines(bound_id);
8372 const unsigned nsub_poly = tmp_vector_polylines.size();
8376 std::ostringstream error_message;
8377 error_message <<
"The boundary (" << bound_id
8378 <<
") was marked to be splitted but\n"
8379 <<
"there are only (" << nsub_poly
8380 <<
") polylines to represent it.\n";
8382 OOMPH_CURRENT_FUNCTION,
8383 OOMPH_EXCEPTION_LOCATION);
8388 for (
unsigned isub = 0; isub < nsub_poly; isub++)
8392 if (!boundary_marked_as_shared_boundary(bound_id, isub))
8394 unsorted_internal_open_polyline_pt.push_back(
8395 tmp_vector_polylines[isub]);
8398 const unsigned nsvertex = tmp_vector_polylines[isub]->nvertex();
8401 std::ostringstream error_message;
8403 <<
"The current chunk (" << isub <<
") of the polyline with\n"
8404 <<
"boundary id (" << bound_id <<
") has no vertices\n";
8406 OOMPH_CURRENT_FUNCTION,
8407 OOMPH_EXCEPTION_LOCATION);
8416 const unsigned nunsorted_internal_open_polyline =
8417 unsorted_internal_open_polyline_pt.size();
8419 if (nunsorted_internal_open_polyline > 0)
8423 sort_polylines_helper(unsorted_internal_open_polyline_pt,
8424 sorted_internal_open_curves_pt);
8444 const unsigned ncurves = nshared_boundary_curves(my_rank);
8445 for (
unsigned i = 0;
i < ncurves;
i++)
8447 const unsigned npolylines = nshared_boundary_polyline(my_rank,
i);
8448 for (
unsigned p = 0; p < npolylines; p++)
8450 const unsigned nvertex =
8451 shared_boundary_polyline_pt(my_rank,
i, p)->nvertex();
8455 shared_boundary_polyline_pt(my_rank,
i, p);
8459 if (this->nshared_boundary_overlaps_internal_boundary() > 0)
8462 const unsigned shd_bnd_id = tmp_shared_poly_pt->
boundary_id();
8466 if (this->shared_boundary_overlaps_internal_boundary(shd_bnd_id))
8468 unsorted_shared_to_internal_polyline_pt.push_back(
8469 tmp_shared_poly_pt);
8472 unsorted_shared_polyline_pt.push_back(tmp_shared_poly_pt);
8478 const unsigned nunsorted_shared_polyline =
8479 unsorted_shared_polyline_pt.size();
8481 if (nunsorted_shared_polyline > 0)
8485 sort_polylines_helper(unsorted_shared_polyline_pt,
8486 sorted_shared_curves_pt);
8496 const unsigned nouter_curves = sorted_outer_curves_pt.size();
8497 const unsigned ninternal_closed_curves =
8498 sorted_internal_closed_curves_pt.size();
8499 const unsigned nshared_curves = sorted_shared_curves_pt.size();
8500 const unsigned ntotal_curves =
8501 nouter_curves + ninternal_closed_curves + nshared_curves;
8504 unsigned counter = 0;
8509 for (
unsigned i = 0;
i < nshared_curves;
i++, counter++)
8511 all_curves_pt[counter] = sorted_shared_curves_pt[
i];
8515 for (
unsigned i = 0;
i < ninternal_closed_curves;
i++, counter++)
8517 all_curves_pt[counter] = sorted_internal_closed_curves_pt[
i];
8521 for (
unsigned i = 0;
i < nouter_curves;
i++, counter++)
8523 all_curves_pt[counter] = sorted_outer_curves_pt[
i];
8528 this->create_tmp_polygons_helper(all_curves_pt, polygons_pt);
8530 this->create_tmp_open_curves_helper(sorted_internal_open_curves_pt,
8531 unsorted_shared_to_internal_polyline_pt,
8545 this->create_shared_polylines_connections();
8562 const unsigned n_holes = this->Internal_polygon_pt.size();
8563 for (
unsigned h = 0; h < n_holes; h++)
8566 this->Internal_polygon_pt[h]->internal_point();
8568 if (!hole_coordinates.empty())
8570 new_holes_coordinates.push_back(hole_coordinates);
8576 if (First_time_compute_holes_left_by_halo_elements)
8579 const unsigned n_extra_holes = Extra_holes_coordinates.size();
8580 for (
unsigned h = 0; h < n_extra_holes; h++)
8583 new_holes_coordinates.push_back(hole_coordinates);
8587 Original_extra_holes_coordinates = Extra_holes_coordinates;
8590 First_time_compute_holes_left_by_halo_elements =
false;
8597 const unsigned n_original_extra_holes =
8598 Original_extra_holes_coordinates.size();
8599 for (
unsigned h = 0; h < n_original_extra_holes; h++)
8601 Vector<double> hole_coordinates = Original_extra_holes_coordinates[h];
8602 new_holes_coordinates.push_back(hole_coordinates);
8608 compute_holes_left_by_halo_elements_helper(new_holes_coordinates);
8612 update_holes_information_helper(polygons_pt, new_holes_coordinates);
8618 Extra_holes_coordinates = new_holes_coordinates;
8630 template<
class ELEMENT>
8645 const unsigned ncurves = polylines_pt.size();
8648 const unsigned nunsorted_curves = ncurves;
8650 unsigned nsorted_curves = 0;
8653 std::vector<bool> done_curve(ncurves);
8658 std::list<Vector<TriangleMeshPolyLine*>> list_building_polygon_pt;
8661 bool root_curve_found =
false;
8666 unsigned root_curve_idx = 0;
8669 for (
unsigned ic = 0; ic < ncurves; ic++)
8671 if (!done_curve[ic])
8673 root_curve_idx = ic;
8676 root_curve_found =
true;
8678 done_curve[ic] =
true;
8685 if (!root_curve_found)
8687 std::stringstream err;
8688 err <<
"The root curve to create a polygon from the shared and "
8689 <<
"original boundaries was not found!!!\n";
8691 "TriangleMesh::create_tmp_polygons_helper()",
8692 OOMPH_EXCEPTION_LOCATION);
8698 polylines_pt[root_curve_idx];
8701 list_building_polygon_pt.push_back(root_curve_pt);
8708 const unsigned nroot_curve_polyline = root_curve_pt.size();
8710 root_curve_pt[0]->initial_vertex_coordinate(root_curve_initial_vertex);
8711 root_curve_pt[nroot_curve_polyline - 1]->final_vertex_coordinate(
8712 root_curve_final_vertex);
8716 ((root_curve_initial_vertex[0] - root_curve_final_vertex[0]) *
8717 (root_curve_initial_vertex[0] - root_curve_final_vertex[0])) +
8718 ((root_curve_initial_vertex[1] - root_curve_final_vertex[1]) *
8719 (root_curve_initial_vertex[1] - root_curve_final_vertex[1]));
8726 nroot_curve_polyline);
8729 for (
unsigned i = 0;
i < nroot_curve_polyline;
i++)
8731 curve_section_pt[
i] = root_curve_pt[
i];
8739 this->Free_polygon_pt.insert(new_polygon_pt);
8742 polygons_pt.push_back(new_polygon_pt);
8749 bool added_curve =
false;
8754 bool polygon_created =
false;
8758 added_curve =
false;
8761 for (
unsigned ic = root_curve_idx + 1; ic < ncurves; ic++)
8763 if (!done_curve[ic])
8770 const unsigned ncurrent_curve_polyline = current_curve_pt.size();
8777 current_curve_pt[0]->initial_vertex_coordinate(
8778 current_curve_initial_vertex);
8779 current_curve_pt[ncurrent_curve_polyline - 1]
8780 ->final_vertex_coordinate(current_curve_final_vertex);
8785 diff = ((current_curve_final_vertex[0] -
8786 root_curve_initial_vertex[0]) *
8787 (current_curve_final_vertex[0] -
8788 root_curve_initial_vertex[0])) +
8789 ((current_curve_final_vertex[1] -
8790 root_curve_initial_vertex[1]) *
8791 (current_curve_final_vertex[1] -
8792 root_curve_initial_vertex[1]));
8798 list_building_polygon_pt.push_front(current_curve_pt);
8800 done_curve[ic] =
true;
8802 root_curve_initial_vertex[0] = current_curve_initial_vertex[0];
8803 root_curve_initial_vertex[1] = current_curve_initial_vertex[1];
8811 diff = ((current_curve_initial_vertex[0] -
8812 root_curve_initial_vertex[0]) *
8813 (current_curve_initial_vertex[0] -
8814 root_curve_initial_vertex[0])) +
8815 ((current_curve_initial_vertex[1] -
8816 root_curve_initial_vertex[1]) *
8817 (current_curve_initial_vertex[1] -
8818 root_curve_initial_vertex[1]));
8824 ncurrent_curve_polyline);
8826 for (
unsigned it = 0; it < ncurrent_curve_polyline; it++)
8828 current_curve_pt[it]->reverse();
8829 tmp_curve_pt[it] = current_curve_pt[it];
8833 for (
int i = ncurrent_curve_polyline - 1;
i >= 0;
i--, count++)
8835 current_curve_pt[count] = tmp_curve_pt[
i];
8838 list_building_polygon_pt.push_front(current_curve_pt);
8840 done_curve[ic] =
true;
8842 root_curve_initial_vertex[0] = current_curve_final_vertex[0];
8843 root_curve_initial_vertex[1] = current_curve_final_vertex[1];
8851 diff = ((current_curve_initial_vertex[0] -
8852 root_curve_final_vertex[0]) *
8853 (current_curve_initial_vertex[0] -
8854 root_curve_final_vertex[0])) +
8855 ((current_curve_initial_vertex[1] -
8856 root_curve_final_vertex[1]) *
8857 (current_curve_initial_vertex[1] -
8858 root_curve_final_vertex[1]));
8864 list_building_polygon_pt.push_back(current_curve_pt);
8866 done_curve[ic] =
true;
8868 root_curve_final_vertex[0] = current_curve_final_vertex[0];
8869 root_curve_final_vertex[1] = current_curve_final_vertex[1];
8878 ((current_curve_final_vertex[0] - root_curve_final_vertex[0]) *
8879 (current_curve_final_vertex[0] - root_curve_final_vertex[0])) +
8880 ((current_curve_final_vertex[1] - root_curve_final_vertex[1]) *
8881 (current_curve_final_vertex[1] - root_curve_final_vertex[1]));
8887 ncurrent_curve_polyline);
8889 for (
unsigned it = 0; it < ncurrent_curve_polyline; it++)
8891 current_curve_pt[it]->reverse();
8892 tmp_curve_pt[it] = current_curve_pt[it];
8896 for (
int i = ncurrent_curve_polyline - 1;
i >= 0;
i--, count++)
8898 current_curve_pt[count] = tmp_curve_pt[
i];
8901 list_building_polygon_pt.push_back(current_curve_pt);
8903 done_curve[ic] =
true;
8905 root_curve_final_vertex[0] = current_curve_initial_vertex[0];
8906 root_curve_final_vertex[1] = current_curve_initial_vertex[1];
8920 ((root_curve_initial_vertex[0] - root_curve_final_vertex[0]) *
8921 (root_curve_initial_vertex[0] - root_curve_final_vertex[0])) +
8922 ((root_curve_initial_vertex[1] - root_curve_final_vertex[1]) *
8923 (root_curve_initial_vertex[1] - root_curve_final_vertex[1]));
8929 added_curve =
false;
8932 polygon_created =
true;
8938 }
while (added_curve);
8941 if (!polygon_created)
8943 std::stringstream error_message;
8945 <<
"It was no possible to create a TriangleMeshPolygon with "
8946 <<
"the input set of curves\n"
8947 <<
"These are the initial and final vertices in the current "
8948 <<
"sorted list of\nTriangleMeshPolyLines\n\n";
8951 unsigned icurve = 0;
8953 list_building_polygon_pt.begin();
8954 it != list_building_polygon_pt.end();
8957 const unsigned ncurrent_curve_polyline = (*it).size();
8958 error_message <<
"TriangleMeshCurve #" << icurve <<
"\n"
8959 <<
"-----------------------------------\n";
8960 for (
unsigned ip = 0; ip < ncurrent_curve_polyline; ip++)
8964 (*it)[ip]->initial_vertex_coordinate(init_vertex);
8965 (*it)[ip]->final_vertex_coordinate(final_vertex);
8966 error_message <<
"TriangleMeshPolyLine #" << ip <<
"\n"
8967 <<
"Initial vertex: (" << init_vertex[0] <<
","
8968 << init_vertex[1] <<
")\n"
8969 <<
"Final vertex: (" << final_vertex[0] <<
","
8970 << final_vertex[1] <<
")\n";
8975 "TriangleMesh::create_tmp_polygons_helper()",
8976 OOMPH_EXCEPTION_LOCATION);
8982 unsigned ntotal_polylines = 0;
8985 list_building_polygon_pt.begin();
8986 it != list_building_polygon_pt.end();
8989 ntotal_polylines += (*it).size();
8996 unsigned counter = 0;
8998 list_building_polygon_pt.begin();
8999 it != list_building_polygon_pt.end();
9002 const unsigned ncurrent_curve_polyline = (*it).size();
9003 for (
unsigned ip = 0; ip < ncurrent_curve_polyline; ip++, counter++)
9005 curve_section_pt[counter] = (*it)[ip];
9014 this->Free_polygon_pt.insert(new_polygon_pt);
9017 polygons_pt.push_back(new_polygon_pt);
9022 }
while (nsorted_curves < nunsorted_curves);
9030 template<
class ELEMENT>
9038 const unsigned ninternal_open_curves = sorted_open_curves_pt.size();
9042 for (
unsigned i = 0;
i < ninternal_open_curves;
i++)
9045 const unsigned npoly = sorted_open_curves_pt[
i].size();
9047 for (
unsigned j = 0; j < npoly; j++)
9049 tmp_curve_section[j] = sorted_open_curves_pt[
i][j];
9056 this->Free_open_curve_pt.insert(new_open_curve_pt);
9059 open_curves_pt.push_back(new_open_curve_pt);
9070 template<
class ELEMENT>
9072 std::set<FiniteElement*>& element_in_processor_pt,
9073 const int& root_edge_bnd_id,
9074 std::map<std::pair<Node*, Node*>,
bool>& overlapped_face,
9075 std::map<
unsigned, std::map<Node*, bool>>&
9076 node_on_bnd_not_overlapped_by_shd_bnd,
9077 std::list<Node*>& current_polyline_nodes,
9078 std::map<
unsigned, std::list<Node*>>& shared_bnd_id_to_sorted_list_node_pt,
9079 const unsigned& node_degree,
9081 const bool called_from_load_balance)
9084 int flag_to_return = -1;
9093 bool overlapping_internal_boundary =
false;
9095 unsigned internal_overlaping_bnd_id = 0;
9096 if (root_edge_bnd_id != -1)
9099 overlapping_internal_boundary =
true;
9101 internal_overlaping_bnd_id =
static_cast<unsigned>(root_edge_bnd_id);
9109 if (new_node_pt->is_on_boundary())
9112 bool is_node_living_in_non_overlapped_boundary =
false;
9116 const unsigned noriginal_bnd = this->initial_shared_boundary_id();
9117 for (
unsigned bb = 0; bb < noriginal_bnd; bb++)
9125 if (overlapping_internal_boundary)
9128 if (new_node_pt->is_on_boundary(bb))
9134 const bool on_bnd_edge_not_overlapped_by_shd_bnd =
9135 node_on_bnd_not_overlapped_by_shd_bnd[bb][new_node_pt];
9136 if (bb != internal_overlaping_bnd_id ||
9137 ((bb == internal_overlaping_bnd_id) &&
9138 (on_bnd_edge_not_overlapped_by_shd_bnd)))
9141 if (bb != internal_overlaping_bnd_id)
9143 is_node_living_in_non_overlapped_boundary =
true;
9153 const unsigned n_bound_ele = this->nboundary_element(bb);
9154 if (n_bound_ele > 0)
9158 for (
unsigned e = 0;
e < n_bound_ele;
e++)
9164 std::set<FiniteElement*>::iterator it =
9165 element_in_processor_pt.find(bulk_ele_pt);
9167 if (it != element_in_processor_pt.end())
9170 bool found_node =
false;
9172 int face_index = this->face_index_at_boundary(bb,
e);
9177 const unsigned n_node_face = face_ele_pt->
nnode();
9179 Node* first_node_pt = face_ele_pt->
node_pt(0);
9180 Node* last_node_pt = face_ele_pt->
node_pt(n_node_face - 1);
9182 std::pair<Node*, Node*> tmp_edge =
9183 std::make_pair(first_node_pt, last_node_pt);
9187 if (!overlapped_face[tmp_edge])
9190 for (
unsigned n = 0; n < n_node_face; n++)
9193 if (face_ele_pt->
node_pt(n) == new_node_pt)
9209 flag_to_return = bb;
9210 return flag_to_return;
9229 if (new_node_pt->is_on_boundary(bb))
9238 const unsigned n_bound_ele = this->nboundary_element(bb);
9239 if (n_bound_ele > 0)
9243 for (
unsigned e = 0;
e < n_bound_ele;
e++)
9249 std::set<FiniteElement*>::iterator it =
9250 element_in_processor_pt.find(bulk_ele_pt);
9252 if (it != element_in_processor_pt.end())
9255 bool found_node =
false;
9257 int face_index = this->face_index_at_boundary(bb,
e);
9262 const unsigned n_node_face = face_ele_pt->
nnode();
9264 Node* first_node_pt = face_ele_pt->
node_pt(0);
9265 Node* last_node_pt = face_ele_pt->
node_pt(n_node_face - 1);
9267 std::pair<Node*, Node*> tmp_edge =
9268 std::make_pair(first_node_pt, last_node_pt);
9272 if (!overlapped_face[tmp_edge])
9275 for (
unsigned n = 0; n < n_node_face; n++)
9278 if (face_ele_pt->
node_pt(n) == new_node_pt)
9294 flag_to_return = bb;
9295 return flag_to_return;
9320 if (!overlapping_internal_boundary)
9325 flag_to_return = -3;
9332 if (is_node_living_in_non_overlapped_boundary)
9334 flag_to_return = -3;
9343 if (flag_to_return >= 0)
9345 return flag_to_return;
9358 for (std::map<
unsigned, std::list<Node*>>::iterator it =
9359 shared_bnd_id_to_sorted_list_node_pt.begin();
9360 it != shared_bnd_id_to_sorted_list_node_pt.end();
9366 const unsigned i_bnd_id = (*it).first;
9369 std::list<Node*>::iterator it_list = (*it).second.begin();
9371 const unsigned n_nodes = (*it).second.size();
9373 for (
unsigned i = 0;
i < n_nodes;
i++, it_list++)
9376 if ((*it_list) == new_node_pt)
9380 candidate_shared_bnd_to_connect.push_back(i_bnd_id);
9391 const unsigned n_candidate_shared_bnd_to_connect =
9392 candidate_shared_bnd_to_connect.size();
9395 if (n_candidate_shared_bnd_to_connect > 0)
9402 if (called_from_load_balance)
9404 return candidate_shared_bnd_to_connect[0];
9417 shared_boundaries_in_this_processor(shared_bound_in_this_proc);
9423 const unsigned n_shared_bound_in_this_proc =
9424 shared_bound_in_this_proc.size();
9427 for (
unsigned i = 0;
i < n_candidate_shared_bnd_to_connect;
i++)
9430 const unsigned i_candidate_shared_bnd =
9431 candidate_shared_bnd_to_connect[
i];
9434 for (
unsigned j = 0; j < n_shared_bound_in_this_proc; j++)
9437 if (i_candidate_shared_bnd == shared_bound_in_this_proc[j])
9440 flag_to_return = i_candidate_shared_bnd;
9441 return flag_to_return;
9452 flag_to_return = -3;
9458 if (flag_to_return >= 0)
9460 return flag_to_return;
9469 unsigned nrepeated = 0;
9470 for (std::list<Node*>::iterator it_list = current_polyline_nodes.begin();
9471 it_list != current_polyline_nodes.end();
9476 if ((*it_list) == new_node_pt)
9488 flag_to_return = -2;
9494 if (node_degree > 2)
9496 flag_to_return = -3;
9500 return flag_to_return;
9510 template<
class ELEMENT>
9514 const unsigned my_rank = this->communicator_pt()->my_rank();
9518 this->Shared_boundary_polyline_pt[my_rank];
9522 const unsigned ncurves = shared_curves_pt.size();
9523 for (
unsigned icurve = 0; icurve < ncurves; icurve++)
9526 const unsigned npoly = shared_curves_pt[icurve].size();
9527 for (
unsigned ipoly = 0; ipoly < npoly; ipoly++)
9533 const unsigned bound_id = shd_poly_pt->
boundary_id();
9536 const bool is_connected_to_the_left =
9540 const bool is_connected_to_the_right =
9546 if (is_connected_to_the_left || is_connected_to_the_right)
9550 const unsigned n_vertex = shd_poly_pt->
nvertex();
9557 if (is_connected_to_the_left)
9561 const unsigned uconnection_to_the_left =
9569 bool connecting_to_an_split_boundary =
false;
9573 bool connecting_to_an_overlaped_boundary =
false;
9576 if (uconnection_to_the_left == bound_id)
9579 poly_to_connect_pt = shd_poly_pt;
9584 const unsigned initial_shd_bnd_id = initial_shared_boundary_id();
9586 if (uconnection_to_the_left >= initial_shd_bnd_id)
9590 poly_to_connect_pt =
9591 boundary_polyline_pt(uconnection_to_the_left);
9599 if (boundary_was_splitted(uconnection_to_the_left))
9601 connecting_to_an_split_boundary =
true;
9611 if (connecting_to_an_split_boundary)
9615 const unsigned n_sub_poly =
9616 nboundary_subpolylines(uconnection_to_the_left);
9621 for (
unsigned ii = 0; ii < n_sub_poly; ii++)
9623 if (boundary_marked_as_shared_boundary(
9624 uconnection_to_the_left, ii))
9628 connecting_to_an_overlaped_boundary =
true;
9639 if (boundary_marked_as_shared_boundary(
9640 uconnection_to_the_left, 0))
9644 connecting_to_an_overlaped_boundary =
true;
9651 if (!(connecting_to_an_split_boundary ||
9652 connecting_to_an_overlaped_boundary))
9656 poly_to_connect_pt =
9657 boundary_polyline_pt(uconnection_to_the_left);
9668 if (!connecting_to_an_split_boundary)
9670 if (boundary_was_splitted(uconnection_to_the_left))
9672 std::stringstream error;
9674 <<
"The current shared boundary (" << bound_id <<
") was "
9675 <<
"marked to have a connection\nto the left with the "
9676 <<
"boundary (" << uconnection_to_the_left <<
").\n"
9677 <<
"The problem is that the destination boundary (possibly\n"
9678 <<
"another shared boundary) is marked to be split\n"
9679 <<
"There should not be split shared boundaries\n\n";
9682 "TriangleMesh::create_shared_polylines_connections()",
9683 OOMPH_EXCEPTION_LOCATION);
9700 if (!connecting_to_an_split_boundary)
9704 if (!connecting_to_an_overlaped_boundary)
9708 unsigned vertex_index = 0;
9710 const bool found_vertex_index =
9711 get_connected_vertex_number_on_destination_polyline(
9712 poly_to_connect_pt, shd_bnd_left_vertex, vertex_index);
9716 if (!found_vertex_index)
9718 std::stringstream error;
9720 <<
"The current shared boundary (" << bound_id <<
") was "
9721 <<
"marked to have a connection\nto the left with the "
9722 <<
"boundary (" << uconnection_to_the_left <<
").\n"
9723 <<
"The problem is that the left vertex of the current\n"
9724 <<
"shared boundary is not in the list of vertices of the\n"
9725 <<
"boundary to connect.\n\n"
9726 <<
"This is the left vertex of the current shared "
9728 <<
"Left vertex: (" << shd_bnd_left_vertex[0] <<
", "
9729 << shd_bnd_left_vertex[1] <<
")\n\n"
9730 <<
"This is the list of vertices on the destination "
9732 const unsigned n_v = poly_to_connect_pt->
nvertex();
9733 for (
unsigned i = 0;
i < n_v;
i++)
9737 error <<
"Vertex #" <<
i <<
": (" << cvertex[0] <<
", "
9738 << cvertex[1] <<
")\n";
9742 "TriangleMesh::create_shared_polylines_connections()",
9743 OOMPH_EXCEPTION_LOCATION);
9750 poly_to_connect_pt, vertex_index);
9760 unsigned vertex_index = 0;
9762 bool found_vertex_index =
false;
9767 get_shared_boundaries_overlapping_internal_boundary(
9768 uconnection_to_the_left, dst_shd_bnd_ids);
9772 const unsigned n_shd_bnd_overlap_int_bnd =
9773 dst_shd_bnd_ids.size();
9777 for (
unsigned ss = 0; ss < n_shd_bnd_overlap_int_bnd; ss++)
9780 const unsigned new_connection_to_the_left =
9781 dst_shd_bnd_ids[ss];
9785 poly_to_connect_pt =
9786 boundary_polyline_pt(new_connection_to_the_left);
9788 if (poly_to_connect_pt != 0)
9792 found_vertex_index =
9793 get_connected_vertex_number_on_destination_polyline(
9794 poly_to_connect_pt, shd_bnd_left_vertex, vertex_index);
9799 if (found_vertex_index)
9809 if (!found_vertex_index)
9811 std::stringstream error;
9813 <<
"The current shared boundary (" << bound_id <<
") was "
9814 <<
"marked to have a connection\nto the left with the "
9815 <<
"boundary (" << uconnection_to_the_left <<
").\n"
9816 <<
"This last boundary is marked to be overlaped by "
9817 <<
"shared boundaries\n"
9818 <<
"The problem is that the left vertex of the current\n"
9819 <<
"shared boundary is not in the list of vertices of the\n"
9820 <<
"boundary to connect.\n\n"
9821 <<
"This is the left vertex of the current shared "
9823 <<
"Left vertex: (" << shd_bnd_left_vertex[0] <<
", "
9824 << shd_bnd_left_vertex[1] <<
")\n\n"
9825 <<
"This is the list of vertices on the destination "
9828 get_shared_boundaries_overlapping_internal_boundary(
9829 uconnection_to_the_left, dst_shd_bnd_ids);
9830 const unsigned n_shd_bnd_overlap_int_bnd =
9831 dst_shd_bnd_ids.size();
9832 for (
unsigned ss = 0; ss < n_shd_bnd_overlap_int_bnd; ss++)
9834 const unsigned new_connection_to_the_left =
9835 dst_shd_bnd_ids[ss];
9836 poly_to_connect_pt =
9837 boundary_polyline_pt(new_connection_to_the_left);
9838 if (poly_to_connect_pt != 0)
9840 const unsigned shd_bnd_id_overlap =
9842 error <<
"Shared boundary id(" << shd_bnd_id_overlap
9844 const unsigned n_v = poly_to_connect_pt->
nvertex();
9845 for (
unsigned i = 0;
i < n_v;
i++)
9849 error <<
"Vertex #" <<
i <<
": (" << cvertex[0] <<
", "
9850 << cvertex[1] <<
")\n";
9857 "TriangleMesh::create_shared_polylines_connections()",
9858 OOMPH_EXCEPTION_LOCATION);
9867 poly_to_connect_pt, vertex_index);
9879 boundary_subpolylines(uconnection_to_the_left);
9882 const unsigned nsub_poly = tmp_vector_subpolylines.size();
9886 std::ostringstream error_message;
9888 <<
"The boundary (" << uconnection_to_the_left <<
") was "
9889 <<
"marked to be splitted but\n"
9890 <<
"there are only (" << nsub_poly <<
") polylines to "
9891 <<
"represent it.\n";
9893 error_message.str(),
9894 "TriangleMesh::create_shared_polylines_connections()",
9895 OOMPH_EXCEPTION_LOCATION);
9907 if (!connecting_to_an_overlaped_boundary)
9913 unsigned vertex_index = 0;
9915 unsigned sub_poly_to_connect = 0;
9917 bool found_vertex_index =
false;
9921 for (
unsigned isub = 0; isub < nsub_poly; isub++)
9924 poly_to_connect_pt = tmp_vector_subpolylines[isub];
9926 found_vertex_index =
9927 get_connected_vertex_number_on_destination_polyline(
9928 poly_to_connect_pt, shd_bnd_left_vertex, vertex_index);
9931 if (found_vertex_index)
9935 sub_poly_to_connect = isub;
9943 if (!found_vertex_index)
9945 std::stringstream error;
9947 <<
"The current shared boundary (" << bound_id <<
") was "
9948 <<
"marked to have a connection\nto the left with the "
9949 <<
"boundary (" << uconnection_to_the_left <<
").\n"
9950 <<
"The problem is that the left vertex of the current\n"
9951 <<
"shared boundary is not in the list of vertices of any\n"
9952 <<
"of the sub polylines that represent the boundary to\n"
9954 <<
"This is the left vertex of the current shared "
9956 <<
"Left vertex: (" << shd_bnd_left_vertex[0] <<
", "
9957 << shd_bnd_left_vertex[1] <<
")\n\n"
9958 <<
"This is the list of vertices on the destination "
9960 for (
unsigned p = 0; p < nsub_poly; p++)
9962 error <<
"Subpolyline #(" << p <<
")\n";
9963 poly_to_connect_pt = tmp_vector_subpolylines[p];
9964 const unsigned n_v = poly_to_connect_pt->
nvertex();
9965 for (
unsigned i = 0;
i < n_v;
i++)
9969 error <<
"Vertex #" <<
i <<
": (" << cvertex[0] <<
", "
9970 << cvertex[1] <<
")\n";
9975 "TriangleMesh::create_shared_polylines_connections()",
9976 OOMPH_EXCEPTION_LOCATION);
9985 poly_to_connect_pt, vertex_index, sub_poly_to_connect);
9996 unsigned vertex_index = 0;
9998 unsigned sub_poly_to_connect = 0;
10000 bool found_vertex_index =
false;
10005 get_shared_boundaries_overlapping_internal_boundary(
10006 uconnection_to_the_left, dst_shd_bnd_ids);
10010 const unsigned n_shd_bnd_overlap_int_bnd =
10011 dst_shd_bnd_ids.size();
10015 for (
unsigned ss = 0; ss < n_shd_bnd_overlap_int_bnd; ss++)
10018 const unsigned new_connection_to_the_left =
10019 dst_shd_bnd_ids[ss];
10023 if (bound_id != new_connection_to_the_left)
10027 poly_to_connect_pt =
10028 boundary_polyline_pt(new_connection_to_the_left);
10030 if (poly_to_connect_pt != 0)
10034 found_vertex_index =
10035 get_connected_vertex_number_on_destination_polyline(
10036 poly_to_connect_pt,
10037 shd_bnd_left_vertex,
10043 if (found_vertex_index)
10055 if (!found_vertex_index)
10059 for (
unsigned isub = 0; isub < nsub_poly; isub++)
10063 if (!boundary_marked_as_shared_boundary(
10064 uconnection_to_the_left, isub))
10067 poly_to_connect_pt = tmp_vector_subpolylines[isub];
10069 found_vertex_index =
10070 get_connected_vertex_number_on_destination_polyline(
10071 poly_to_connect_pt,
10072 shd_bnd_left_vertex,
10076 if (found_vertex_index)
10080 sub_poly_to_connect = isub;
10093 if (!found_vertex_index)
10095 std::stringstream error;
10097 <<
"The current shared boundary (" << bound_id <<
") was "
10098 <<
"marked to have a connection\nto the left with the "
10099 <<
"boundary (" << uconnection_to_the_left <<
").\n"
10100 <<
"This last boundary is marked to be overlaped by "
10101 <<
"shared boundaries\n"
10102 <<
"The problem is that the left vertex of the current\n"
10103 <<
"shared boundary is not in the list of vertices of "
10104 <<
"the\nboundary to connect.\n\n"
10105 <<
"This is the left vertex of the current shared "
10107 <<
"Left vertex: (" << shd_bnd_left_vertex[0] <<
", "
10108 << shd_bnd_left_vertex[1] <<
")\n\n"
10109 <<
"This is the list of vertices on the destination "
10110 <<
"boundary (only those subpolylines not marked as "
10111 <<
"overlaped by\nshared boundaries)\n";
10112 for (
unsigned p = 0; p < nsub_poly; p++)
10114 if (!boundary_marked_as_shared_boundary(
10115 uconnection_to_the_left, p))
10117 error <<
"Subpolyline #(" << p <<
")\n";
10118 poly_to_connect_pt = tmp_vector_subpolylines[p];
10119 const unsigned n_v = poly_to_connect_pt->
nvertex();
10120 for (
unsigned i = 0;
i < n_v;
i++)
10124 error <<
"Vertex #" <<
i <<
": (" << cvertex[0] <<
", "
10125 << cvertex[1] <<
")\n";
10129 error <<
"\nThis is the list of vertices of the shared "
10130 <<
"polylines that overlap\nthe internal "
10133 get_shared_boundaries_overlapping_internal_boundary(
10134 uconnection_to_the_left, dst_shd_bnd_ids);
10135 const unsigned n_shd_bnd_overlap_int_bnd =
10136 dst_shd_bnd_ids.size();
10137 for (
unsigned ss = 0; ss < n_shd_bnd_overlap_int_bnd; ss++)
10139 const unsigned new_connection_to_the_left =
10140 dst_shd_bnd_ids[ss];
10141 poly_to_connect_pt =
10142 boundary_polyline_pt(new_connection_to_the_left);
10143 if (poly_to_connect_pt != 0)
10145 const unsigned shd_bnd_id_overlap =
10147 error <<
"Shared boundary id(" << shd_bnd_id_overlap
10149 const unsigned n_v = poly_to_connect_pt->
nvertex();
10150 for (
unsigned i = 0;
i < n_v;
i++)
10154 error <<
"Vertex #" <<
i <<
": (" << cvertex[0] <<
", "
10155 << cvertex[1] <<
")\n";
10162 "TriangleMesh::create_shared_polylines_connections()",
10163 OOMPH_EXCEPTION_LOCATION);
10172 poly_to_connect_pt, vertex_index, sub_poly_to_connect);
10182 if (is_connected_to_the_right)
10186 const unsigned uconnection_to_the_right =
10194 bool connecting_to_an_split_boundary =
false;
10198 bool connecting_to_an_overlaped_boundary =
false;
10201 if (uconnection_to_the_right == bound_id)
10204 poly_to_connect_pt = shd_poly_pt;
10209 const unsigned initial_shd_bnd_id = initial_shared_boundary_id();
10211 if (uconnection_to_the_right >= initial_shd_bnd_id)
10215 poly_to_connect_pt =
10216 boundary_polyline_pt(uconnection_to_the_right);
10224 if (boundary_was_splitted(uconnection_to_the_right))
10226 connecting_to_an_split_boundary =
true;
10236 if (connecting_to_an_split_boundary)
10240 const unsigned n_sub_poly =
10241 nboundary_subpolylines(uconnection_to_the_right);
10246 for (
unsigned ii = 0; ii < n_sub_poly; ii++)
10248 if (boundary_marked_as_shared_boundary(
10249 uconnection_to_the_right, ii))
10253 connecting_to_an_overlaped_boundary =
true;
10264 if (boundary_marked_as_shared_boundary(
10265 uconnection_to_the_right, 0))
10269 connecting_to_an_overlaped_boundary =
true;
10276 if (!(connecting_to_an_split_boundary ||
10277 connecting_to_an_overlaped_boundary))
10281 poly_to_connect_pt =
10282 boundary_polyline_pt(uconnection_to_the_right);
10293 if (!connecting_to_an_split_boundary)
10295 if (boundary_was_splitted(uconnection_to_the_right))
10297 std::stringstream error;
10299 <<
"The current shared boundary (" << bound_id <<
") was "
10300 <<
"marked to have a connection\nto the right with the "
10301 <<
"boundary (" << uconnection_to_the_right <<
").\n"
10302 <<
"The problem is that the destination boundary (possibly\n"
10303 <<
"another shared boundary) is marked to be split\n"
10304 <<
"There should not be split shared boundaries\n\n";
10307 "TriangleMesh::create_shared_polylines_connections()",
10308 OOMPH_EXCEPTION_LOCATION);
10326 if (!connecting_to_an_split_boundary)
10330 if (!connecting_to_an_overlaped_boundary)
10335 unsigned vertex_index = 0;
10336 const bool found_vertex_index =
10337 get_connected_vertex_number_on_destination_polyline(
10338 poly_to_connect_pt, shd_bnd_right_vertex, vertex_index);
10342 if (!found_vertex_index)
10344 std::stringstream error;
10346 <<
"The current shared boundary (" << bound_id <<
") was "
10347 <<
"marked to have a connection\nto the right with the "
10348 <<
"boundary (" << uconnection_to_the_right <<
").\n"
10349 <<
"The problem is that the right vertex of the current\n"
10350 <<
"shared boundary is not in the list of vertices of the\n"
10351 <<
"boundary to connect.\n\n"
10352 <<
"This is the right vertex of the current shared "
10354 <<
"Right vertex: (" << shd_bnd_right_vertex[0] <<
", "
10355 << shd_bnd_right_vertex[1] <<
")\n\n"
10356 <<
"This is the list of vertices on the destination "
10358 const unsigned n_v = poly_to_connect_pt->
nvertex();
10359 for (
unsigned i = 0;
i < n_v;
i++)
10363 error <<
"Vertex #" <<
i <<
": (" << cvertex[0] <<
", "
10364 << cvertex[1] <<
")\n";
10368 "TriangleMesh::create_shared_polylines_connections()",
10369 OOMPH_EXCEPTION_LOCATION);
10376 poly_to_connect_pt, vertex_index);
10386 unsigned vertex_index = 0;
10388 bool found_vertex_index =
false;
10393 get_shared_boundaries_overlapping_internal_boundary(
10394 uconnection_to_the_right, dst_shd_bnd_ids);
10398 const unsigned n_shd_bnd_overlap_int_bnd =
10399 dst_shd_bnd_ids.size();
10403 for (
unsigned ss = 0; ss < n_shd_bnd_overlap_int_bnd; ss++)
10406 const unsigned new_connection_to_the_right =
10407 dst_shd_bnd_ids[ss];
10411 poly_to_connect_pt =
10412 boundary_polyline_pt(new_connection_to_the_right);
10414 if (poly_to_connect_pt != 0)
10418 found_vertex_index =
10419 get_connected_vertex_number_on_destination_polyline(
10420 poly_to_connect_pt, shd_bnd_right_vertex, vertex_index);
10425 if (found_vertex_index)
10435 if (!found_vertex_index)
10437 std::stringstream error;
10439 <<
"The current shared boundary (" << bound_id <<
") was "
10440 <<
"marked to have a connection\nto the right with the "
10441 <<
"boundary (" << uconnection_to_the_right <<
").\n"
10442 <<
"This last boundary is marked to be overlaped by "
10443 <<
"shared boundaries\n"
10444 <<
"The problem is that the right vertex of the current\n"
10445 <<
"shared boundary is not in the list of vertices of the\n"
10446 <<
"boundary to connect.\n\n"
10447 <<
"This is the right vertex of the current shared "
10449 <<
"Right vertex: (" << shd_bnd_right_vertex[0] <<
", "
10450 << shd_bnd_right_vertex[1] <<
")\n\n"
10451 <<
"This is the list of vertices on the destination "
10454 get_shared_boundaries_overlapping_internal_boundary(
10455 uconnection_to_the_right, dst_shd_bnd_ids);
10456 const unsigned n_shd_bnd_overlap_int_bnd =
10457 dst_shd_bnd_ids.size();
10458 for (
unsigned ss = 0; ss < n_shd_bnd_overlap_int_bnd; ss++)
10460 const unsigned new_connection_to_the_right =
10461 dst_shd_bnd_ids[ss];
10462 poly_to_connect_pt =
10463 boundary_polyline_pt(new_connection_to_the_right);
10464 if (poly_to_connect_pt != 0)
10466 const unsigned shd_bnd_id_overlap =
10468 error <<
"Shared boundary id(" << shd_bnd_id_overlap
10470 const unsigned n_v = poly_to_connect_pt->
nvertex();
10471 for (
unsigned i = 0;
i < n_v;
i++)
10475 error <<
"Vertex #" <<
i <<
": (" << cvertex[0] <<
", "
10476 << cvertex[1] <<
")\n";
10483 "TriangleMesh::create_shared_polylines_connections()",
10484 OOMPH_EXCEPTION_LOCATION);
10493 poly_to_connect_pt, vertex_index);
10505 boundary_subpolylines(uconnection_to_the_right);
10508 const unsigned nsub_poly = tmp_vector_subpolylines.size();
10510 if (nsub_poly <= 1)
10512 std::ostringstream error_message;
10514 <<
"The boundary (" << uconnection_to_the_right <<
") was "
10515 <<
"marked to be splitted but\n"
10516 <<
"there are only (" << nsub_poly <<
") polylines to "
10517 <<
"represent it.\n";
10519 error_message.str(),
10520 "TriangleMesh::create_shared_polylines_connections()",
10521 OOMPH_EXCEPTION_LOCATION);
10534 if (!connecting_to_an_overlaped_boundary)
10540 unsigned vertex_index = 0;
10542 unsigned sub_poly_to_connect = 0;
10544 bool found_vertex_index =
false;
10548 for (
unsigned isub = 0; isub < nsub_poly; isub++)
10551 poly_to_connect_pt = tmp_vector_subpolylines[isub];
10553 found_vertex_index =
10554 get_connected_vertex_number_on_destination_polyline(
10555 poly_to_connect_pt, shd_bnd_right_vertex, vertex_index);
10558 if (found_vertex_index)
10562 sub_poly_to_connect = isub;
10570 if (!found_vertex_index)
10572 std::stringstream error;
10574 <<
"The current shared boundary (" << bound_id <<
") was "
10575 <<
"marked to have a connection\nto the right with the "
10576 <<
"boundary (" << uconnection_to_the_right <<
").\n"
10577 <<
"The problem is that the right vertex of the current\n"
10578 <<
"shared boundary is not in the list of vertices of any\n"
10579 <<
"of the sub polylines that represent the boundary to\n"
10581 <<
"This is the right vertex of the current shared "
10583 <<
"Right vertex: (" << shd_bnd_right_vertex[0] <<
", "
10584 << shd_bnd_right_vertex[1] <<
")\n\n"
10585 <<
"This is the list of vertices on the destination "
10587 for (
unsigned p = 0; p < nsub_poly; p++)
10589 error <<
"Subpolyline #(" << p <<
")\n";
10590 poly_to_connect_pt = tmp_vector_subpolylines[p];
10591 const unsigned n_v = poly_to_connect_pt->
nvertex();
10592 for (
unsigned i = 0;
i < n_v;
i++)
10596 error <<
"Vertex #" <<
i <<
": (" << cvertex[0] <<
", "
10597 << cvertex[1] <<
")\n";
10602 "TriangleMesh::create_shared_polylines_connections()",
10603 OOMPH_EXCEPTION_LOCATION);
10612 poly_to_connect_pt, vertex_index, sub_poly_to_connect);
10623 unsigned vertex_index = 0;
10625 unsigned sub_poly_to_connect = 0;
10627 bool found_vertex_index =
false;
10632 get_shared_boundaries_overlapping_internal_boundary(
10633 uconnection_to_the_right, dst_shd_bnd_ids);
10637 const unsigned n_shd_bnd_overlap_int_bnd =
10638 dst_shd_bnd_ids.size();
10642 for (
unsigned ss = 0; ss < n_shd_bnd_overlap_int_bnd; ss++)
10645 const unsigned new_connection_to_the_right =
10646 dst_shd_bnd_ids[ss];
10650 if (bound_id != new_connection_to_the_right)
10654 poly_to_connect_pt =
10655 boundary_polyline_pt(new_connection_to_the_right);
10657 if (poly_to_connect_pt != 0)
10661 found_vertex_index =
10662 get_connected_vertex_number_on_destination_polyline(
10663 poly_to_connect_pt,
10664 shd_bnd_right_vertex,
10670 if (found_vertex_index)
10682 if (!found_vertex_index)
10686 for (
unsigned isub = 0; isub < nsub_poly; isub++)
10690 if (!boundary_marked_as_shared_boundary(
10691 uconnection_to_the_right, isub))
10694 poly_to_connect_pt = tmp_vector_subpolylines[isub];
10696 found_vertex_index =
10697 get_connected_vertex_number_on_destination_polyline(
10698 poly_to_connect_pt,
10699 shd_bnd_right_vertex,
10703 if (found_vertex_index)
10707 sub_poly_to_connect = isub;
10720 if (!found_vertex_index)
10722 std::stringstream error;
10724 <<
"The current shared boundary (" << bound_id <<
") was "
10725 <<
"marked to have a connection\nto the right with the "
10726 <<
"boundary (" << uconnection_to_the_right <<
").\n"
10727 <<
"This last boundary is marked to be overlaped by "
10728 <<
"shared boundaries\n"
10729 <<
"The problem is that the right vertex of the current\n"
10730 <<
"shared boundary is not in the list of vertices of "
10731 <<
"the\nboundary to connect.\n\n"
10732 <<
"This is the right vertex of the current shared "
10734 <<
"Right vertex: (" << shd_bnd_right_vertex[0] <<
", "
10735 << shd_bnd_right_vertex[1] <<
")\n\n"
10736 <<
"This is the list of vertices on the destination "
10737 <<
"boundary (only those subpolylines not marked as "
10738 <<
"overlaped by\nshared boundaries)\n";
10739 for (
unsigned p = 0; p < nsub_poly; p++)
10741 if (!boundary_marked_as_shared_boundary(
10742 uconnection_to_the_right, p))
10744 error <<
"Subpolyline #(" << p <<
")\n";
10745 poly_to_connect_pt = tmp_vector_subpolylines[p];
10746 const unsigned n_v = poly_to_connect_pt->
nvertex();
10747 for (
unsigned i = 0;
i < n_v;
i++)
10751 error <<
"Vertex #" <<
i <<
": (" << cvertex[0] <<
", "
10752 << cvertex[1] <<
")\n";
10756 error <<
"\nThis is the list of vertices of the shared "
10757 <<
"polylines that overlap\nthe internal "
10760 get_shared_boundaries_overlapping_internal_boundary(
10761 uconnection_to_the_right, dst_shd_bnd_ids);
10762 const unsigned n_shd_bnd_overlap_int_bnd =
10763 dst_shd_bnd_ids.size();
10764 for (
unsigned ss = 0; ss < n_shd_bnd_overlap_int_bnd; ss++)
10766 const unsigned new_connection_to_the_right =
10767 dst_shd_bnd_ids[ss];
10768 poly_to_connect_pt =
10769 boundary_polyline_pt(new_connection_to_the_right);
10770 if (poly_to_connect_pt != 0)
10772 const unsigned shd_bnd_id_overlap =
10774 error <<
"Shared boundary id(" << shd_bnd_id_overlap
10776 const unsigned n_v = poly_to_connect_pt->
nvertex();
10777 for (
unsigned i = 0;
i < n_v;
i++)
10781 error <<
"Vertex #" <<
i <<
": (" << cvertex[0] <<
", "
10782 << cvertex[1] <<
")\n";
10789 "TriangleMesh::create_shared_polylines_connections()",
10790 OOMPH_EXCEPTION_LOCATION);
10799 poly_to_connect_pt, vertex_index, sub_poly_to_connect);
10818 template<
class ELEMENT>
10823 const unsigned n_proc = this->communicator_pt()->nproc();
10824 const unsigned my_rank = this->communicator_pt()->my_rank();
10828 std::map<FiniteElement*, bool> done_ele;
10832 for (
unsigned iproc = 0; iproc < n_proc; iproc++)
10835 if (iproc != my_rank)
10838 const unsigned n_shd_bnd_iproc = nshared_boundaries(my_rank, iproc);
10843 const unsigned n_shd_bnd_iproc_rev = nshared_boundaries(iproc, my_rank);
10844 if (n_shd_bnd_iproc != n_shd_bnd_iproc_rev)
10846 std::ostringstream error_stream;
10848 <<
"The number of shared boundaries of processor (" << my_rank
10849 <<
") with processor(" << iproc <<
"): (" << n_shd_bnd_iproc
10851 <<
"is different from the number of shared boundaries of "
10852 <<
"processor (" << iproc <<
")\nwith processor (" << my_rank
10853 <<
"): (" << n_shd_bnd_iproc <<
")\n\n";
10855 OOMPH_CURRENT_FUNCTION,
10856 OOMPH_EXCEPTION_LOCATION);
10862 for (
unsigned i = 0;
i < n_shd_bnd_iproc;
i++)
10865 const unsigned shd_bnd_id = shared_boundaries_ids(my_rank, iproc,
i);
10868 const unsigned n_shd_bnd_ele = nshared_boundary_element(shd_bnd_id);
10871 for (
unsigned e = 0;
e < n_shd_bnd_ele;
e++)
10874 FiniteElement* ele_pt = shared_boundary_element_pt(shd_bnd_id,
e);
10880 if (!done_ele[ele_pt])
10883 const unsigned n_nodes = ele_pt->nnode();
10888 for (
unsigned k = 0; k < n_nodes; k++)
10890 Node* tmp_node_pt = ele_pt->node_pt(k);
10892 for (
unsigned d = 0; d < 2; d++)
10894 element_centroid[d] += tmp_node_pt->x(d);
10899 for (
unsigned d = 0; d < 2; d++)
10901 element_centroid[d] = element_centroid[d] / (double)n_nodes;
10905 output_holes_coordinates.push_back(element_centroid);
10927 template<
class ELEMENT>
10948 const unsigned n_input_holes = output_holes_coordinates.size();
10951 if (n_input_holes == 0)
10957 const unsigned n_polygons = polygons_pt.size();
10966 for (
unsigned p = 0; p < n_polygons; p++)
10969 const unsigned n_polylines = polygons_pt[p]->npolyline();
10971 for (
unsigned pp = 0; pp < n_polylines; pp++)
10975 polygons_pt[p]->polyline_pt(pp);
10977 const unsigned n_vertices = tmp_poly_pt->
nvertex();
10981 for (
unsigned v = 0; v < n_vertices - 1; v++)
10985 vertices_polygons[p].push_back(current_vertex);
10997 std::vector<bool> is_outer_polygon(n_polygons,
true);
11001 if (n_polygons > 1)
11010 for (
unsigned p = 0; p < n_polygons; p++)
11016 const unsigned n_vertices = tmp_inner_polygon.size();
11019 polygon_edge_middle_vertex[p].resize(n_vertices - 1);
11023 for (
unsigned e = 0;
e < n_vertices - 1;
e++)
11026 const unsigned dim = 2;
11027 polygon_edge_middle_vertex[p][
e].resize(dim);
11028 for (
unsigned d = 0; d < dim; d++)
11030 polygon_edge_middle_vertex[p][
e][d] =
11031 (tmp_inner_polygon[
e][d] + tmp_inner_polygon[
e + 1][d]) / 2.0;
11040 for (
unsigned idx_inner = 0; idx_inner < n_polygons; idx_inner++)
11045 bool is_inner_polygon =
false;
11050 for (
unsigned i = 0;
i < n_polygons;
i++)
11053 if (
i != idx_inner)
11056 const unsigned n_edges =
11057 polygon_edge_middle_vertex[idx_inner].size();
11060 for (
unsigned e = 0;
e < n_edges;
e++)
11064 polygon_edge_middle_vertex[idx_inner][
e];
11067 const bool is_point_inside = is_point_inside_polygon_helper(
11068 vertices_polygons[
i], current_vertex);
11072 if (is_point_inside)
11075 is_inner_polygon =
true;
11086 if (is_inner_polygon)
11096 if (is_inner_polygon)
11099 is_outer_polygon[idx_inner] =
false;
11105 is_outer_polygon[idx_inner] =
true;
11114 unsigned n_outer_polygons = 0;
11115 unsigned n_inner_polygons = 0;
11119 for (
unsigned i = 0;
i < n_polygons;
i++)
11121 if (is_outer_polygon[
i])
11124 n_outer_polygons++;
11129 n_inner_polygons++;
11131 index_inner_polygon.push_back(
i);
11150 std::vector<bool> is_inside_an_inner_polygon(n_input_holes,
false);
11154 std::vector<bool> is_outside_the_outer_polygons(n_input_holes,
true);
11158 std::vector<bool> is_inside_the_convex_hull(n_input_holes,
false);
11167 for (
unsigned i = 0;
i < n_inner_polygons;
i++)
11170 const unsigned ii = index_inner_polygon[
i];
11173 for (
unsigned h = 0; h < n_input_holes; h++)
11177 if (!is_inside_an_inner_polygon[h])
11180 const bool is_inside_polygon = is_point_inside_polygon_helper(
11181 vertices_polygons[ii], output_holes_coordinates[h]);
11185 if (is_inside_polygon)
11188 is_inside_an_inner_polygon[h] =
true;
11190 vertex_inside_inner_polygon[
i].push_back(
11191 output_holes_coordinates[h]);
11203 for (
unsigned h = 0; h < n_input_holes; h++)
11207 if (!is_inside_an_inner_polygon[h])
11211 for (
unsigned i = 0;
i < n_polygons;
i++)
11214 if (is_outer_polygon[
i])
11217 const bool is_inside_polygon = is_point_inside_polygon_helper(
11218 vertices_polygons[
i], output_holes_coordinates[h]);
11223 if (is_inside_polygon)
11226 is_outside_the_outer_polygons[h] =
false;
11240 is_outside_the_outer_polygons[h] =
false;
11247 std::vector<Point> input_vertices_convex_hull;
11250 for (
unsigned p = 0; p < n_polygons; p++)
11253 const unsigned n_vertices = vertices_polygons[p].size();
11255 for (
unsigned v = 0; v < n_vertices; v++)
11260 point.
x = vertices_polygons[p][v][0];
11261 point.
y = vertices_polygons[p][v][1];
11263 input_vertices_convex_hull.push_back(point);
11268 std::vector<Point> output_vertices_convex_hull =
11269 convex_hull(input_vertices_convex_hull);
11272 const unsigned n_vertices_convex_hull = output_vertices_convex_hull.size();
11276 for (
unsigned i = 0;
i < n_vertices_convex_hull;
i++)
11279 vertices_convex_hull[
i].resize(2);
11281 vertices_convex_hull[
i][0] = output_vertices_convex_hull[
i].x;
11282 vertices_convex_hull[
i][1] = output_vertices_convex_hull[
i].y;
11288 for (
unsigned h = 0; h < n_input_holes; h++)
11291 if (is_outside_the_outer_polygons[h])
11294 const bool is_inside_convex_hull = is_point_inside_polygon_helper(
11295 vertices_convex_hull, output_holes_coordinates[h]);
11298 if (is_inside_convex_hull)
11301 is_inside_the_convex_hull[h] =
true;
11308 is_inside_the_convex_hull[h] =
true;
11316 for (
unsigned h = 0; h < n_input_holes; h++)
11319 if ((is_inside_an_inner_polygon[h]) ||
11320 (is_outside_the_outer_polygons[h] && is_inside_the_convex_hull[h]))
11323 hole_kept.push_back(output_holes_coordinates[h]);
11328 output_holes_coordinates.clear();
11330 output_holes_coordinates = hole_kept;
11337 template<
class ELEMENT>
11342 unsigned n_unsorted_polylines = unsorted_polylines_pt.size();
11343 unsigned n_sorted_polylines = 0;
11344 unsigned curves_index = 0;
11347 std::map<TriangleMeshPolyLine*, bool> done_polyline;
11353 std::list<TriangleMeshPolyLine*> sorted_polyline_list_pt;
11354 bool changes =
false;
11363 bool found_root_polyline =
false;
11364 while (pp < n_unsorted_polylines && !found_root_polyline)
11366 if (!done_polyline[unsorted_polylines_pt[pp]])
11368 found_root_polyline =
true;
11377 if (pp < n_unsorted_polylines)
11380 left_pt = right_pt = unsorted_polylines_pt[pp];
11381 done_polyline[left_pt] =
true;
11383 n_sorted_polylines++;
11387 sorted_polyline_list_pt.push_back(left_pt);
11399 for (
unsigned i = pp + 1;
i < n_unsorted_polylines;
i++)
11402 unsorted_polylines_pt[
i];
11403 if (!done_polyline[current_polyline_pt])
11414 if (left_vertex == final_vertex)
11416 left_pt = current_polyline_pt;
11417 sorted_polyline_list_pt.push_front(left_pt);
11418 done_polyline[left_pt] =
true;
11419 n_sorted_polylines++;
11425 else if (right_vertex == initial_vertex)
11427 right_pt = current_polyline_pt;
11428 sorted_polyline_list_pt.push_back(right_pt);
11429 done_polyline[right_pt] =
true;
11430 n_sorted_polylines++;
11436 else if (left_vertex == initial_vertex)
11438 current_polyline_pt->
reverse();
11439 left_pt = current_polyline_pt;
11440 sorted_polyline_list_pt.push_front(left_pt);
11441 done_polyline[left_pt] =
true;
11442 n_sorted_polylines++;
11448 else if (right_vertex == final_vertex)
11450 current_polyline_pt->
reverse();
11451 right_pt = current_polyline_pt;
11452 sorted_polyline_list_pt.push_back(right_pt);
11453 done_polyline[right_pt] =
true;
11454 n_sorted_polylines++;
11475 if (!found_root_polyline)
11477 std::stringstream err;
11478 err <<
"It was not possible to find a root polyline to sort the "
11479 <<
"others around it.\nThe number of unsorted and sorted "
11480 <<
"polylines is different, it means that\nnot all the "
11481 <<
"polylines have been sorted.\n"
11482 <<
"Found root polyline: (" << found_root_polyline <<
")\n"
11483 <<
"Sorted polylines: (" << n_sorted_polylines <<
")\n"
11484 <<
"Unsorted polylines: (" << n_unsorted_polylines <<
")\n";
11486 "TriangleMesh::sort_polylines_helper()",
11487 OOMPH_EXCEPTION_LOCATION);
11494 unsigned n_sorted_polyline_on_list = sorted_polyline_list_pt.size();
11498 n_sorted_polyline_on_list);
11499 unsigned counter = 0;
11501 std::list<TriangleMeshPolyLine*>::iterator it_polyline;
11502 for (it_polyline = sorted_polyline_list_pt.begin();
11503 it_polyline != sorted_polyline_list_pt.end();
11506 tmp_sorted_polylines[counter] = *it_polyline;
11510 sorted_polylines_pt.push_back(tmp_sorted_polylines);
11514 }
while (n_sorted_polylines < n_unsorted_polylines);
11519 if (n_sorted_polylines != n_unsorted_polylines)
11521 std::stringstream err;
11522 err <<
"The number of polylines on the unsorted and sorted vectors"
11523 <<
" is different,\n"
11524 <<
"it means that not all the polylines have been sorted.\n"
11525 <<
"Sorted polylines: " << n_sorted_polylines
11526 <<
"\nUnsorted polylines: " << n_unsorted_polylines;
11528 "TriangleMesh::sort_polylines_helper()",
11529 OOMPH_EXCEPTION_LOCATION);
11537 template<
class ELEMENT>
11543 std::map<
Data*, std::set<unsigned>>& processors_associated_with_data,
11544 const bool& overrule_keep_as_halo_element_status)
11547 const unsigned nproc = comm_pt->nproc();
11548 const unsigned my_rank = comm_pt->my_rank();
11556 for (
unsigned iproc = 0; iproc < nproc; iproc++)
11558 halo_element_pt[iproc].resize(nproc);
11564 std::map<GeneralisedElement*, unsigned> element_to_global_index;
11567 this->get_halo_elements_on_all_procs(nproc,
11570 processors_associated_with_data,
11571 overrule_keep_as_halo_element_status,
11572 element_to_global_index,
11576 flush_shared_boundary_polyline_pt();
11577 Shared_boundary_polyline_pt.resize(nproc);
11583 std::set<FiniteElement*> element_in_processor_pt;
11584 const unsigned n_ele = backed_up_f_el_pt.size();
11585 for (
unsigned e = 0;
e < n_ele;
e++)
11587 if (element_domain[
e] == my_rank)
11589 element_in_processor_pt.insert(backed_up_f_el_pt[
e]);
11596 std::map<std::pair<Node*, Node*>,
unsigned> elements_edges_on_boundary;
11597 this->get_element_edges_on_boundary(elements_edges_on_boundary);
11601 this->create_polylines_from_halo_elements_helper(
11603 element_to_global_index,
11604 element_in_processor_pt,
11606 elements_edges_on_boundary,
11607 Shared_boundary_polyline_pt);
11615 template<
class ELEMENT>
11617 const unsigned& nproc,
11620 std::map<
Data*, std::set<unsigned>>& processors_associated_with_data,
11621 const bool& overrule_keep_as_halo_element_status,
11622 std::map<GeneralisedElement*, unsigned>& element_to_global_index,
11625 const unsigned n_ele = backed_up_el_pt.size();
11628 for (
unsigned iproc = 0; iproc < nproc; iproc++)
11635 for (
unsigned e = 0;
e < n_ele;
e++)
11639 unsigned el_domain = element_domain[
e];
11643 if (el_domain != iproc)
11648 if ((this->Keep_all_elements_as_halos) ||
11651 if (!overrule_keep_as_halo_element_status)
11655 if (!already_added[el_domain][el_pt])
11657 output_halo_elements_pt[iproc][el_domain].push_back(el_pt);
11658 already_added[el_domain][el_pt] =
true;
11659 element_to_global_index[el_pt] =
e;
11668 if (finite_el_pt != 0)
11670 unsigned n_node = finite_el_pt->
nnode();
11671 for (
unsigned n = 0; n < n_node; n++)
11673 Node* nod_pt = finite_el_pt->
node_pt(n);
11676 std::set<unsigned>::iterator it =
11677 processors_associated_with_data[nod_pt].find(iproc);
11678 if (it != processors_associated_with_data[nod_pt].end())
11682 if (!already_added[el_domain][el_pt])
11684 output_halo_elements_pt[iproc][el_domain].push_back(el_pt);
11685 already_added[el_domain][el_pt] =
true;
11686 element_to_global_index[el_pt] =
e;
11704 template<
class ELEMENT>
11706 std::map<std::pair<Node*, Node*>,
unsigned>& element_edges_on_boundary)
11709 const unsigned nbound = this->nboundary();
11711 for (
unsigned b = 0; b < nbound; b++)
11714 std::map<std::pair<Node*, Node*>,
bool> edge_done;
11716 const unsigned nbound_ele = this->nboundary_element(b);
11717 for (
unsigned e = 0;
e < nbound_ele;
e++)
11722 int face_index = this->face_index_at_boundary(b,
e);
11727 const unsigned nnodes = face_ele_pt->
nnode();
11729 Node* first_node_pt = face_ele_pt->
node_pt(0);
11730 Node* last_node_pt = face_ele_pt->
node_pt(nnodes - 1);
11733 std::pair<Node*, Node*> edge =
11734 std::make_pair(first_node_pt, last_node_pt);
11737 if (!edge_done[edge])
11740 edge_done[edge] =
true;
11743 std::pair<Node*, Node*> inv_edge =
11744 std::make_pair(last_node_pt, first_node_pt);
11747 edge_done[inv_edge] =
true;
11750 element_edges_on_boundary[edge] = b;
11754 delete face_ele_pt;
11769 template<
class ELEMENT>
11772 std::map<GeneralisedElement*, unsigned>& element_to_global_index,
11773 std::set<FiniteElement*>& element_in_processor_pt,
11775 std::map<std::pair<Node*, Node*>,
unsigned>& elements_edges_on_boundary,
11778 const unsigned nproc = this->communicator_pt()->nproc();
11779 const unsigned my_rank = this->communicator_pt()->my_rank();
11804 std::map<std::pair<Node*, Node*>,
bool> overlapped_edge;
11810 Shared_boundaries_ids.resize(nproc);
11811 for (
unsigned j = 0; j < nproc; j++)
11813 edges[j].resize(nproc);
11814 edge_element_pt[j].resize(nproc);
11815 edge_element_face[j].resize(nproc);
11816 edge_boundary[j].resize(nproc);
11819 Shared_boundaries_ids[j].resize(nproc);
11825 for (
unsigned iproc = 0; iproc < nproc; iproc++)
11832 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
11849 halo_elements_iproc_with_jproc = input_halo_elements[iproc][jproc];
11852 const unsigned nhalo_elements_iproc_with_jproc =
11853 halo_elements_iproc_with_jproc.size();
11855 if (nhalo_elements_iproc_with_jproc > 0)
11858 halo_elements_jproc_with_iproc = input_halo_elements[jproc][iproc];
11862 const unsigned nhalo_elements_jproc_with_iproc =
11863 halo_elements_jproc_with_iproc.size();
11866 if (nhalo_elements_jproc_with_iproc == 0)
11871 std::stringstream err;
11872 err <<
"There are no halo elements from processor (" << jproc
11874 <<
"with processor (" << iproc <<
").\n"
11875 <<
"This is strange since there are halo elements from "
11876 <<
"processor (" << iproc <<
") with processor (" << jproc
11878 <<
"Number of halo elements from (" << iproc <<
") to ("
11879 << jproc <<
") : (" << nhalo_elements_iproc_with_jproc <<
")\n"
11880 <<
"Number of halo elements from (" << jproc <<
") to ("
11881 << iproc <<
") : (" << nhalo_elements_jproc_with_iproc <<
")\n";
11884 "TriangleMesh::create_polylines_from_halo_elements_helper()",
11885 OOMPH_EXCEPTION_LOCATION);
11890 unsigned halo_edges_counter_iproc = 0;
11892 unsigned halo_edges_counter_jproc = 0;
11896 edgesi_to_element_pt;
11900 std::map<std::pair<std::pair<Node*, Node*>,
FiniteElement*>,
int>
11901 edgesi_element_pt_to_face_index;
11905 edgesj_to_element_pt;
11909 std::map<std::pair<std::pair<Node*, Node*>,
FiniteElement*>,
int>
11910 edgesj_element_pt_to_face_index;
11916 for (
unsigned ih = 0; ih < nhalo_elements_iproc_with_jproc; ih++)
11920 element_to_global_index[halo_elements_iproc_with_jproc[ih]];
11922 if (element_domain[
e] != jproc)
11925 std::stringstream err;
11926 err <<
"There was a problem on the ihalo-jhalo classification.\n"
11927 <<
"One of the elements, (the one with the (" <<
e <<
")-th "
11928 <<
"index ) is not on the (" << jproc <<
")-th processor\n"
11929 <<
"but it was stored as a halo element of processor ("
11930 << iproc <<
") with processor (" << jproc <<
").\n";
11933 "TriangleMesh::create_polylines_from_halo_elements_helper()",
11934 OOMPH_EXCEPTION_LOCATION);
11939 dynamic_cast<FiniteElement*
>(halo_elements_iproc_with_jproc[ih]);
11943 std::stringstream err;
11944 err <<
"The halo element (" << ih
11945 <<
") could not be casted to the "
11946 <<
"FiniteElement type.\n";
11949 "TriangleMesh::create_polylines_from_halo_elements_helper()",
11950 OOMPH_EXCEPTION_LOCATION);
11955 const unsigned n_nodes = el_pt->
nnode();
11962 std::stringstream err;
11963 err <<
"The number of nodes of the " << ih
11964 <<
"-th halo element is"
11965 <<
" (" << n_nodes <<
").\nWe can not work with triangle "
11966 <<
"elements with less than three nodes\n";
11969 "TriangleMesh::create_polylines_from_halo_elements_helper()",
11970 OOMPH_EXCEPTION_LOCATION);
11975 Node* first_node_pt = el_pt->
node_pt(0);
11976 Node* second_node_pt = el_pt->
node_pt(1);
11977 Node* third_node_pt = el_pt->
node_pt(2);
11980 halo_edges_iproc.push_back(first_node_pt);
11981 halo_edges_iproc.push_back(second_node_pt);
11982 halo_edges_counter_jproc++;
11984 halo_edges_iproc.push_back(second_node_pt);
11985 halo_edges_iproc.push_back(third_node_pt);
11986 halo_edges_counter_jproc++;
11988 halo_edges_iproc.push_back(third_node_pt);
11989 halo_edges_iproc.push_back(first_node_pt);
11990 halo_edges_counter_jproc++;
11993 std::pair<Node*, Node*> edge1 =
11994 std::make_pair(first_node_pt, second_node_pt);
11995 edgesi_to_element_pt[edge1] = el_pt;
11997 std::pair<Node*, Node*> edge2 =
11998 std::make_pair(second_node_pt, third_node_pt);
11999 edgesi_to_element_pt[edge2] = el_pt;
12001 std::pair<Node*, Node*> edge3 =
12002 std::make_pair(third_node_pt, first_node_pt);
12003 edgesi_to_element_pt[edge3] = el_pt;
12006 std::pair<std::pair<Node*, Node*>,
FiniteElement*> edge_ele1 =
12007 std::make_pair(edge1, el_pt);
12008 edgesi_element_pt_to_face_index[edge_ele1] = 2;
12010 std::pair<std::pair<Node*, Node*>,
FiniteElement*> edge_ele2 =
12011 std::make_pair(edge2, el_pt);
12012 edgesi_element_pt_to_face_index[edge_ele2] = 0;
12014 std::pair<std::pair<Node*, Node*>,
FiniteElement*> edge_ele3 =
12015 std::make_pair(edge3, el_pt);
12016 edgesi_element_pt_to_face_index[edge_ele3] = 1;
12024 for (
unsigned jh = 0; jh < nhalo_elements_jproc_with_iproc; jh++)
12028 element_to_global_index[halo_elements_jproc_with_iproc[jh]];
12030 if (element_domain[
e] != iproc)
12033 std::stringstream err;
12034 err <<
"There was a problem on the jhalo-ihalo classification.\n"
12035 <<
"One of the elements, (the one with the (" <<
e <<
")-th "
12036 <<
"index ) is not on the (" << iproc <<
")-th processor\n"
12037 <<
"but it was stored as a halo element of processor ("
12038 << jproc <<
") with processor (" << iproc <<
").\n";
12041 "TriangleMesh::create_polylines_from_halo_elements_helper()",
12042 OOMPH_EXCEPTION_LOCATION);
12047 dynamic_cast<FiniteElement*
>(halo_elements_jproc_with_iproc[jh]);
12050 std::stringstream err;
12051 err <<
"The halo element (" << jh
12052 <<
") could not be casted to the "
12053 <<
"FiniteElement type.\n";
12056 "TriangleMesh::create_polylines_from_halo_elements_helper()",
12057 OOMPH_EXCEPTION_LOCATION);
12062 const unsigned n_nodes = el_pt->
nnode();
12069 std::stringstream err;
12070 err <<
"The number of nodes of the " << jh
12071 <<
"-th halo element is"
12072 <<
" (" << n_nodes <<
").\nWe can not work with triangle "
12073 <<
"elements with less than three nodes\n";
12076 "TriangleMesh::create_polylines_from_halo_elements_helper()",
12077 OOMPH_EXCEPTION_LOCATION);
12082 Node* first_node_pt = el_pt->
node_pt(0);
12083 Node* second_node_pt = el_pt->
node_pt(1);
12084 Node* third_node_pt = el_pt->
node_pt(2);
12087 halo_edges_jproc.push_back(first_node_pt);
12088 halo_edges_jproc.push_back(second_node_pt);
12089 halo_edges_counter_iproc++;
12091 halo_edges_jproc.push_back(second_node_pt);
12092 halo_edges_jproc.push_back(third_node_pt);
12093 halo_edges_counter_iproc++;
12095 halo_edges_jproc.push_back(third_node_pt);
12096 halo_edges_jproc.push_back(first_node_pt);
12097 halo_edges_counter_iproc++;
12100 std::pair<Node*, Node*> edge1 =
12101 std::make_pair(first_node_pt, second_node_pt);
12102 edgesj_to_element_pt[edge1] = el_pt;
12104 std::pair<Node*, Node*> edge2 =
12105 std::make_pair(second_node_pt, third_node_pt);
12106 edgesj_to_element_pt[edge2] = el_pt;
12108 std::pair<Node*, Node*> edge3 =
12109 std::make_pair(third_node_pt, first_node_pt);
12110 edgesj_to_element_pt[edge3] = el_pt;
12113 std::pair<std::pair<Node*, Node*>,
FiniteElement*> edge_ele1 =
12114 std::make_pair(edge1, el_pt);
12115 edgesj_element_pt_to_face_index[edge_ele1] = 2;
12117 std::pair<std::pair<Node*, Node*>,
FiniteElement*> edge_ele2 =
12118 std::make_pair(edge2, el_pt);
12119 edgesj_element_pt_to_face_index[edge_ele2] = 0;
12121 std::pair<std::pair<Node*, Node*>,
FiniteElement*> edge_ele3 =
12122 std::make_pair(edge3, el_pt);
12123 edgesj_element_pt_to_face_index[edge_ele3] = 1;
12136 unsigned nhalo_iedges = halo_edges_iproc.size();
12137 unsigned nhalo_jedges = halo_edges_jproc.size();
12141 for (
unsigned ihe = 0; ihe < nhalo_iedges; ihe += 2)
12145 ihalo_edge[0] = halo_edges_iproc[ihe];
12146 ihalo_edge[1] = halo_edges_iproc[ihe + 1];
12149 std::pair<Node*, Node*> tmp_edge =
12150 std::make_pair(ihalo_edge[0], ihalo_edge[1]);
12154 int edge_boundary_id = -1;
12156 std::map<std::pair<Node*, Node*>,
unsigned>::iterator it;
12157 it = elements_edges_on_boundary.find(tmp_edge);
12160 if (it != elements_edges_on_boundary.end())
12164 edge_boundary_id = (*it).second;
12170 std::pair<Node*, Node*> rtmp_edge =
12171 std::make_pair(ihalo_edge[1], ihalo_edge[0]);
12172 it = elements_edges_on_boundary.find(rtmp_edge);
12173 if (it != elements_edges_on_boundary.end())
12177 edge_boundary_id = (*it).second;
12184 for (
unsigned jhe = 0; jhe < nhalo_jedges; jhe += 2)
12188 jhalo_edge[0] = halo_edges_jproc[jhe];
12189 jhalo_edge[1] = halo_edges_jproc[jhe + 1];
12192 if (ihalo_edge[0] == jhalo_edge[0] &&
12193 ihalo_edge[1] == jhalo_edge[1])
12196 std::pair<Node*, Node*> new_edge =
12197 std::make_pair(ihalo_edge[0], ihalo_edge[1]);
12203 haloi_ele_pt = edgesi_to_element_pt[new_edge];
12205 haloj_ele_pt = edgesj_to_element_pt[new_edge];
12208 if (haloi_ele_pt == 0 || haloj_ele_pt == 0)
12210 std::stringstream err;
12211 err <<
"There is no associated elements with the new "
12212 <<
"shared boundary. This is an storing problem,\n"
12213 <<
"possibly related with a memory leak problem!!!\n"
12214 <<
"The nodes that compound the edge are these:\n"
12215 <<
"On processor (" << iproc <<
"):\n"
12216 <<
"(" << ihalo_edge[0]->x(0) <<
", "
12217 << ihalo_edge[0]->x(1) <<
") and (" << ihalo_edge[1]->x(0)
12218 <<
", " << ihalo_edge[1]->x(1) <<
")\n\n"
12219 <<
"On processor (" << jproc <<
"):\n"
12220 <<
"(" << jhalo_edge[0]->x(0) <<
", "
12221 << jhalo_edge[0]->x(1) <<
") and (" << jhalo_edge[1]->x(0)
12222 <<
", " << jhalo_edge[1]->x(1) <<
")\n\n"
12223 <<
"The nodes coordinates should be the same!!!\n";
12225 "TriangleMesh::create_polylines_from_"
12226 "halo_elements_helper()",
12227 OOMPH_EXCEPTION_LOCATION);
12231 edges[iproc][jproc].push_back(new_edge);
12234 if (edge_boundary_id >= 0)
12237 overlapped_edge[new_edge] =
true;
12240 std::pair<Node*, Node*> rev_new_edge =
12241 std::make_pair(ihalo_edge[1], ihalo_edge[0]);
12244 overlapped_edge[rev_new_edge] =
true;
12250 edge_boundary[iproc][jproc].push_back(edge_boundary_id);
12254 tmp_elements_pt.push_back(haloi_ele_pt);
12255 tmp_elements_pt.push_back(haloj_ele_pt);
12258 edge_element_pt[iproc][jproc].push_back(tmp_elements_pt);
12265 edge_elementi_pair = make_pair(new_edge, haloi_ele_pt);
12268 edge_elementj_pair = make_pair(new_edge, haloj_ele_pt);
12272 int face_index_haloi_ele = -1;
12273 face_index_haloi_ele =
12274 edgesi_element_pt_to_face_index[edge_elementi_pair];
12275 int face_index_haloj_ele = -1;
12276 face_index_haloj_ele =
12277 edgesj_element_pt_to_face_index[edge_elementj_pair];
12279 if (face_index_haloi_ele == -1 || face_index_haloj_ele == -1)
12281 std::stringstream err;
12282 err <<
"There is no associated face indexes to the"
12283 <<
"elements that gave\nrise to the shared edge\n"
12284 <<
"The nodes that compound the edge are these:\n"
12285 <<
"On processor (" << iproc <<
"):\n"
12286 <<
"(" << ihalo_edge[0]->x(0) <<
", "
12287 << ihalo_edge[0]->x(1) <<
") and (" << ihalo_edge[1]->x(0)
12288 <<
", " << ihalo_edge[1]->x(1) <<
")\n\n"
12289 <<
"On processor (" << jproc <<
"):\n"
12290 <<
"(" << jhalo_edge[0]->x(0) <<
", "
12291 << jhalo_edge[0]->x(1) <<
") and (" << jhalo_edge[1]->x(0)
12292 <<
", " << jhalo_edge[1]->x(1) <<
")\n\n"
12293 <<
"The nodes coordinates should be the same!!!\n";
12295 "TriangleMesh::create_polylines_from_"
12296 "halo_elements_helper()",
12297 OOMPH_EXCEPTION_LOCATION);
12303 tmp_edge_element_face_index.push_back(face_index_haloi_ele);
12304 tmp_edge_element_face_index.push_back(face_index_haloj_ele);
12306 edge_element_face[iproc][jproc].push_back(
12307 tmp_edge_element_face_index);
12315 else if (ihalo_edge[0] == jhalo_edge[1] &&
12316 ihalo_edge[1] == jhalo_edge[0])
12319 std::pair<Node*, Node*> new_edge =
12320 std::make_pair(ihalo_edge[0], ihalo_edge[1]);
12325 haloi_ele_pt = edgesi_to_element_pt[new_edge];
12330 std::pair<Node*, Node*> new_edge_reversed =
12331 std::make_pair(jhalo_edge[0], jhalo_edge[1]);
12332 haloj_ele_pt = edgesj_to_element_pt[new_edge_reversed];
12335 if (haloi_ele_pt == 0 || haloj_ele_pt == 0)
12337 std::stringstream err;
12338 err <<
"There is no associated elements with the new "
12339 <<
"shared boundary (reversed version). This is an "
12340 <<
"storing problem, possibly related with a memory "
12341 <<
"leak problem!!!\n"
12342 <<
"The nodes that compound the edge are these:\n"
12343 <<
"On processor (" << iproc <<
"):\n"
12344 <<
"(" << ihalo_edge[0]->x(0) <<
", "
12345 << ihalo_edge[0]->x(1) <<
") and (" << ihalo_edge[1]->x(0)
12346 <<
", " << ihalo_edge[1]->x(1) <<
")\n\n"
12347 <<
"On processor (" << jproc <<
"):\n"
12348 <<
"(" << jhalo_edge[0]->x(0) <<
", "
12349 << jhalo_edge[0]->x(1) <<
") and (" << jhalo_edge[1]->x(0)
12350 <<
", " << jhalo_edge[1]->x(1) <<
")\n\n"
12351 <<
"The nodes coordinates should be the same!!!\n";
12353 "TriangleMesh::create_polylines_from_"
12354 "halo_elements_helper()",
12355 OOMPH_EXCEPTION_LOCATION);
12359 edges[iproc][jproc].push_back(new_edge);
12362 if (edge_boundary_id >= 0)
12365 overlapped_edge[new_edge] =
true;
12368 std::pair<Node*, Node*> rev_new_edge =
12369 std::make_pair(ihalo_edge[1], ihalo_edge[0]);
12372 overlapped_edge[rev_new_edge] =
true;
12377 edge_boundary[iproc][jproc].push_back(edge_boundary_id);
12381 tmp_elements_pt.push_back(haloi_ele_pt);
12382 tmp_elements_pt.push_back(haloj_ele_pt);
12385 edge_element_pt[iproc][jproc].push_back(tmp_elements_pt);
12392 edge_elementi_pair = make_pair(new_edge, haloi_ele_pt);
12395 edge_elementj_pair =
12396 make_pair(new_edge_reversed, haloj_ele_pt);
12400 int face_index_haloi_ele = -1;
12401 face_index_haloi_ele =
12402 edgesi_element_pt_to_face_index[edge_elementi_pair];
12403 int face_index_haloj_ele = -1;
12404 face_index_haloj_ele =
12405 edgesj_element_pt_to_face_index[edge_elementj_pair];
12407 if (face_index_haloi_ele == -1 || face_index_haloj_ele == -1)
12409 std::stringstream err;
12410 err <<
"There is no associated face indexes to the"
12411 <<
"elements that gave\nrise to the shared edge\n"
12412 <<
"The nodes that compound the edge are these:\n"
12413 <<
"On processor (" << iproc <<
"):\n"
12414 <<
"(" << ihalo_edge[0]->x(0) <<
", "
12415 << ihalo_edge[0]->x(1) <<
") and (" << ihalo_edge[1]->x(0)
12416 <<
", " << ihalo_edge[1]->x(1) <<
")\n\n"
12417 <<
"On processor (" << jproc <<
"):\n"
12418 <<
"(" << jhalo_edge[0]->x(0) <<
", "
12419 << jhalo_edge[0]->x(1) <<
") and (" << jhalo_edge[1]->x(0)
12420 <<
", " << jhalo_edge[1]->x(1) <<
")\n\n"
12421 <<
"The nodes coordinates should be the same!!!\n";
12423 "TriangleMesh::create_polylines_from_"
12424 "halo_elements_helper()",
12425 OOMPH_EXCEPTION_LOCATION);
12431 tmp_edge_element_face_index.push_back(face_index_haloi_ele);
12432 tmp_edge_element_face_index.push_back(face_index_haloj_ele);
12434 edge_element_face[iproc][jproc].push_back(
12435 tmp_edge_element_face_index);
12460 std::map<Node*, unsigned> global_shared_node_degree;
12464 std::map<std::pair<Node*, Node*>,
bool> edge_done;
12467 std::map<Node*, bool> node_done;
12471 for (
unsigned iproc = 0; iproc < nproc; iproc++)
12478 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
12481 const unsigned nshd_edges = edges[iproc][jproc].size();
12487 const unsigned nedge_element = edge_element_pt[iproc][jproc].size();
12488 if (nshd_edges != nedge_element)
12490 std::stringstream error_message;
12492 <<
"The number of shared edges between processor iproc and jproc\n"
12493 <<
"is different form the number of edge elements between the\n"
12494 <<
"pair of processors\n"
12495 <<
"iproc: (" << iproc <<
")\n"
12496 <<
"jproc: (" << jproc <<
")\n"
12497 <<
"# of shared edges: (" << nshd_edges <<
")\n"
12498 <<
"# of edge elements: (" << nedge_element <<
")\n\n";
12500 error_message.str(),
12501 "TriangleMesh::create_polylines_from_halo_elements_helper()",
12502 OOMPH_EXCEPTION_LOCATION);
12506 const unsigned nedge_element_face =
12507 edge_element_face[iproc][jproc].size();
12508 if (nshd_edges != nedge_element_face)
12510 std::stringstream error_message;
12512 <<
"The number of shared edges between processor iproc and jproc\n"
12513 <<
"is different form the number of edge element faces between "
12515 <<
"pair of processors\n"
12516 <<
"iproc: (" << iproc <<
")\n"
12517 <<
"jproc: (" << jproc <<
")\n"
12518 <<
"# of shared edges: (" << nshd_edges <<
")\n"
12519 <<
"# of edge element faces: (" << nedge_element_face <<
")\n\n";
12521 error_message.str(),
12522 "TriangleMesh::create_polylines_from_halo_elements_helper()",
12523 OOMPH_EXCEPTION_LOCATION);
12527 const unsigned nedge_boundary = edge_boundary[iproc][jproc].size();
12528 if (nshd_edges != nedge_boundary)
12530 std::stringstream error_message;
12532 <<
"The number of shared edges between processor iproc and jproc\n"
12533 <<
"is different form the number of edge boundaries ids between "
12535 <<
"pair of processors\n"
12536 <<
"iproc: (" << iproc <<
")\n"
12537 <<
"jproc: (" << jproc <<
")\n"
12538 <<
"# of shared edges: (" << nshd_edges <<
")\n"
12539 <<
"# of edge boundaries ids: (" << nedge_boundary <<
")\n\n";
12541 error_message.str(),
12542 "TriangleMesh::create_polylines_from_halo_elements_helper()",
12543 OOMPH_EXCEPTION_LOCATION);
12549 for (
unsigned se = 0; se < nshd_edges; se++)
12552 std::pair<Node*, Node*> edge = edges[iproc][jproc][se];
12555 if (edge_done[edge])
12557 std::stringstream error_message;
12559 <<
"The shared edge between processor iproc and processor\n"
12560 <<
"jproc has been already visited, this is weird since the\n"
12561 <<
"edge should not be shared by other pair of processors\n"
12562 <<
"iproc: (" << iproc <<
")\n"
12563 <<
"jproc: (" << jproc <<
")\n"
12564 <<
"First node of edge: (" << edge.first->x(0) <<
", "
12565 << edge.first->x(1) <<
")\n"
12566 <<
"Second node of edge: (" << edge.second->x(0) <<
", "
12567 << edge.second->x(1) <<
")\n"
12568 <<
"Associated edge boundary id: ("
12569 << edge_boundary[iproc][jproc][se] <<
")\n\n";
12571 error_message.str(),
12572 "TriangleMesh::create_polylines_from_halo_elements_helper()",
12573 OOMPH_EXCEPTION_LOCATION);
12577 edge_done[edge] =
true;
12579 std::pair<Node*, Node*> rev_edge =
12580 std::make_pair(edge.second, edge.first);
12582 edge_done[rev_edge] =
true;
12586 Node* left_node_pt = edge.first;
12587 Node* right_node_pt = edge.second;
12590 if (!node_done[left_node_pt])
12594 global_shared_node_degree[left_node_pt] = 1;
12600 global_shared_node_degree[left_node_pt]++;
12604 if (!node_done[right_node_pt])
12608 global_shared_node_degree[right_node_pt] = 1;
12613 global_shared_node_degree[right_node_pt]++;
12628 std::map<unsigned, std::map<Node*, bool>>
12629 node_on_bnd_not_overlapped_by_shd_bnd;
12632 for (std::map<std::pair<Node*, Node*>,
unsigned>::iterator it_map =
12633 elements_edges_on_boundary.begin();
12634 it_map != elements_edges_on_boundary.end();
12638 std::pair<Node*, Node*> edge_pair = (*it_map).first;
12641 if (!overlapped_edge[edge_pair])
12645 unsigned b = (*it_map).second;
12648 Node* left_node_pt = edge_pair.first;
12649 node_on_bnd_not_overlapped_by_shd_bnd[b][left_node_pt] =
true;
12652 Node* right_node_pt = edge_pair.second;
12653 node_on_bnd_not_overlapped_by_shd_bnd[b][right_node_pt] =
true;
12673 std::map<unsigned, std::list<Node*>> shared_bnd_id_to_sorted_list_node_pt;
12677 unsigned shared_boundary_id_start = this->nboundary();
12678 Initial_shared_boundary_id = shared_boundary_id_start;
12684 for (
unsigned iproc = 0; iproc < nproc; iproc++)
12691 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
12699 unsigned npolylines_counter = 0;
12700 const unsigned nedges = edges[iproc][jproc].size();
12706 unsigned nsorted_edges = 0;
12709 std::map<std::pair<Node*, Node*>,
bool> edge_done;
12713 while (nsorted_edges < nedges)
12717 std::list<FiniteElement*> tmp_boundary_element_pt;
12720 std::list<int> tmp_face_index_element;
12722 std::pair<Node*, Node*> edge;
12724 bool found_initial_edge =
false;
12726 int root_edge_bound_id = -1;
12727 unsigned iedge = 0;
12728 for (iedge = 0; iedge < nedges; iedge++)
12730 edge = edges[iproc][jproc][iedge];
12732 if (!edge_done[edge])
12735 root_edge_bound_id = edge_boundary[iproc][jproc][iedge];
12737 found_initial_edge =
true;
12746 if (!found_initial_edge)
12748 std::ostringstream error_message;
12750 <<
"All the edge are already done, but the number of done\n"
12751 <<
"edges (" << nsorted_edges
12752 <<
") is still less than the total\n"
12753 <<
"number of edges (" << nedges <<
").\n";
12756 error_message.str(),
12757 "TriangleMesh::create_polylines_from_halo_elements_helper()",
12758 OOMPH_EXCEPTION_LOCATION);
12764 std::list<Node*> sorted_nodes;
12765 sorted_nodes.clear();
12768 Node* first_node_pt = edge.first;
12769 Node* last_node_pt = edge.second;
12772 sorted_nodes.push_back(first_node_pt);
12773 sorted_nodes.push_back(last_node_pt);
12777 tmp_boundary_element_pt.push_back(
12778 edge_element_pt[iproc][jproc][iedge - 1][0]);
12779 tmp_boundary_element_pt.push_back(
12780 edge_element_pt[iproc][jproc][iedge - 1][1]);
12784 tmp_face_index_element.push_back(
12785 edge_element_face[iproc][jproc][iedge - 1][0]);
12786 tmp_face_index_element.push_back(
12787 edge_element_face[iproc][jproc][iedge - 1][1]);
12790 edge_done[edge] =
true;
12795 bool node_added =
true;
12799 bool node_added_to_the_left =
true;
12800 bool node_added_to_the_right =
true;
12818 bool connection_to_the_left =
false;
12823 bool connection_to_the_right =
false;
12827 bool current_polyline_has_connections_at_both_ends =
false;
12834 int bound_id_connection_to_the_left = -1;
12835 int bound_id_connection_to_the_right = -1;
12838 const unsigned first_node_degree =
12839 global_shared_node_degree[first_node_pt];
12843 bound_id_connection_to_the_left = check_connections_of_polyline_nodes(
12844 element_in_processor_pt,
12845 root_edge_bound_id,
12847 node_on_bnd_not_overlapped_by_shd_bnd,
12849 shared_bnd_id_to_sorted_list_node_pt,
12859 if (bound_id_connection_to_the_left != -1)
12861 connection_to_the_left =
true;
12865 const unsigned last_node_degree =
12866 global_shared_node_degree[last_node_pt];
12870 bound_id_connection_to_the_right =
12871 check_connections_of_polyline_nodes(
12872 element_in_processor_pt,
12873 root_edge_bound_id,
12875 node_on_bnd_not_overlapped_by_shd_bnd,
12877 shared_bnd_id_to_sorted_list_node_pt,
12886 if (bound_id_connection_to_the_right != -1)
12888 connection_to_the_right =
true;
12893 if (connection_to_the_left && connection_to_the_right)
12895 current_polyline_has_connections_at_both_ends =
true;
12903 while (node_added && (nsorted_edges < nedges) &&
12904 !current_polyline_has_connections_at_both_ends)
12909 for (
unsigned iiedge = iedge; iiedge < nedges; iiedge++)
12912 node_added =
false;
12913 node_added_to_the_left =
false;
12914 node_added_to_the_right =
false;
12916 edge = edges[iproc][jproc][iiedge];
12917 const int edge_bound_id = edge_boundary[iproc][jproc][iiedge];
12923 if (!edge_done[edge] && (edge_bound_id == root_edge_bound_id))
12926 Node* left_node_pt = edge.first;
12927 Node* right_node_pt = edge.second;
12930 Node* new_added_node_pt = 0;
12933 if (left_node_pt == first_node_pt && !connection_to_the_left)
12936 sorted_nodes.push_front(right_node_pt);
12938 new_added_node_pt = first_node_pt = right_node_pt;
12942 node_added_to_the_left =
true;
12945 else if (left_node_pt == last_node_pt &&
12946 !connection_to_the_right)
12949 sorted_nodes.push_back(right_node_pt);
12951 new_added_node_pt = last_node_pt = right_node_pt;
12955 node_added_to_the_right =
true;
12958 else if (right_node_pt == first_node_pt &&
12959 !connection_to_the_left)
12962 sorted_nodes.push_front(left_node_pt);
12964 new_added_node_pt = first_node_pt = left_node_pt;
12968 node_added_to_the_left =
true;
12971 else if (right_node_pt == last_node_pt &&
12972 !connection_to_the_right)
12975 sorted_nodes.push_back(left_node_pt);
12977 new_added_node_pt = last_node_pt = left_node_pt;
12981 node_added_to_the_right =
true;
12991 edge_done[edge] =
true;
12995 const unsigned added_node_degree =
12996 global_shared_node_degree[new_added_node_pt];
12998 if (node_added_to_the_left)
13001 tmp_boundary_element_pt.push_front(
13002 edge_element_pt[iproc][jproc][iiedge][1]);
13003 tmp_boundary_element_pt.push_front(
13004 edge_element_pt[iproc][jproc][iiedge][0]);
13006 tmp_face_index_element.push_front(
13007 edge_element_face[iproc][jproc][iiedge][1]);
13008 tmp_face_index_element.push_front(
13009 edge_element_face[iproc][jproc][iiedge][0]);
13012 if (node_added_to_the_right)
13015 tmp_boundary_element_pt.push_back(
13016 edge_element_pt[iproc][jproc][iiedge][0]);
13017 tmp_boundary_element_pt.push_back(
13018 edge_element_pt[iproc][jproc][iiedge][1]);
13020 tmp_face_index_element.push_back(
13021 edge_element_face[iproc][jproc][iiedge][0]);
13022 tmp_face_index_element.push_back(
13023 edge_element_face[iproc][jproc][iiedge][1]);
13033 if (node_added_to_the_left && !connection_to_the_left)
13036 bound_id_connection_to_the_left =
13037 check_connections_of_polyline_nodes(
13038 element_in_processor_pt,
13039 root_edge_bound_id,
13041 node_on_bnd_not_overlapped_by_shd_bnd,
13043 shared_bnd_id_to_sorted_list_node_pt,
13045 new_added_node_pt);
13052 if (bound_id_connection_to_the_left != -1)
13054 connection_to_the_left =
true;
13064 if (node_added_to_the_right && !connection_to_the_right)
13067 bound_id_connection_to_the_right =
13068 check_connections_of_polyline_nodes(
13069 element_in_processor_pt,
13070 root_edge_bound_id,
13072 node_on_bnd_not_overlapped_by_shd_bnd,
13074 shared_bnd_id_to_sorted_list_node_pt,
13076 new_added_node_pt);
13083 if (bound_id_connection_to_the_right != -1)
13085 connection_to_the_right =
true;
13093 if (connection_to_the_left && connection_to_the_right)
13095 current_polyline_has_connections_at_both_ends =
true;
13119 const unsigned n_bnd_ele = tmp_boundary_element_pt.size();
13125 unsigned help_counter = 0;
13127 for (std::list<FiniteElement*>::iterator it_bnd_ele =
13128 tmp_boundary_element_pt.begin();
13129 it_bnd_ele != tmp_boundary_element_pt.end();
13132 tmp_bnd_ele_pt[help_counter++] = (*it_bnd_ele);
13137 for (std::list<int>::iterator it_face_idx =
13138 tmp_face_index_element.begin();
13139 it_face_idx != tmp_face_index_element.end();
13142 tmp_face_idx_ele[help_counter++] = (*it_face_idx);
13155 Vector<int> final_bound_id_connection_to_the_left;
13158 Vector<int> final_bound_id_connection_to_the_right;
13161 break_loops_on_shared_polyline_helper(
13162 shared_boundary_id_start,
13166 bound_id_connection_to_the_left,
13167 bound_id_connection_to_the_right,
13168 final_sorted_nodes_pt,
13169 final_boundary_element_pt,
13170 final_face_index_element,
13171 final_bound_id_connection_to_the_left,
13172 final_bound_id_connection_to_the_right);
13175 const unsigned n_final_sorted_nodes = final_sorted_nodes_pt.size();
13178 for (
unsigned i = 0;
i < n_final_sorted_nodes;
i++)
13183 shared_bnd_id_to_sorted_list_node_pt[shared_boundary_id_start] =
13184 final_sorted_nodes_pt[
i];
13188 create_shared_polyline(my_rank,
13189 shared_boundary_id_start,
13192 final_sorted_nodes_pt[
i],
13193 root_edge_bound_id,
13194 final_boundary_element_pt[
i],
13195 final_face_index_element[
i],
13196 unsorted_polylines_pt,
13197 final_bound_id_connection_to_the_left[
i],
13198 final_bound_id_connection_to_the_right[
i]);
13202 npolylines_counter++;
13206 shared_boundary_id_start++;
13219 if (unsorted_polylines_pt[iproc].size() > 0)
13223 sort_polylines_helper(unsorted_polylines_pt[iproc],
13224 output_polylines_pt[iproc]);
13228 const unsigned nunsorted_polylines_iproc =
13229 unsorted_polylines_pt[iproc].size();
13232 unsigned tmp_ntotal_polylines = 0;
13234 for (
unsigned ii = 0; ii < output_polylines_pt[iproc].size(); ii++)
13236 tmp_ntotal_polylines += output_polylines_pt[iproc][ii].size();
13238 if (tmp_ntotal_polylines != nunsorted_polylines_iproc)
13240 std::ostringstream error_message;
13241 error_message <<
" The total number of unsorted polylines ("
13242 << nunsorted_polylines_iproc
13243 <<
") in common with\nprocessor (" << iproc
13244 <<
") is different from the total number of sorted "
13245 <<
"polylines (" << tmp_ntotal_polylines
13246 <<
") with\nthe same "
13249 OOMPH_CURRENT_FUNCTION,
13250 OOMPH_EXCEPTION_LOCATION);
13257 this->Final_shared_boundary_id = shared_boundary_id_start;
13264 template<
class ELEMENT>
13266 const unsigned& initial_shd_bnd_id,
13267 std::list<Node*>& input_nodes,
13270 const int& input_connect_to_the_left,
13271 const int& input_connect_to_the_right,
13272 Vector<std::list<Node*>>& output_sorted_nodes_pt,
13279 Node* left_node_pt = input_nodes.front();
13280 Node* right_node_pt = input_nodes.back();
13289 std::list<Node*>::iterator it = input_nodes.begin();
13292 unsigned counter = 0;
13295 while (it != input_nodes.end())
13300 if (it == input_nodes.end())
13312 std::list<Node*> sub_nodes;
13321 sub_nodes.push_back(*it);
13331 sub_nodes.push_back((*it));
13334 sub_bnd_ele_pt.push_back(input_boundary_element_pt[counter]);
13335 sub_bnd_ele_pt.push_back(input_boundary_element_pt[counter + 1]);
13338 sub_face_idx_ele.push_back(input_face_index_element[counter]);
13339 sub_face_idx_ele.push_back(input_face_index_element[counter + 1]);
13346 }
while ((*it) != left_node_pt && (*it) != right_node_pt &&
13347 it != input_nodes.end());
13350 tmp_sub_nodes.push_back(sub_nodes);
13352 tmp_sub_bnd_ele_pt.push_back(sub_bnd_ele_pt);
13354 tmp_sub_face_idx_ele.push_back(sub_face_idx_ele);
13362 const unsigned n_sub_list = tmp_sub_nodes.size();
13365 if (n_sub_list > 3)
13367 std::stringstream error_message;
13369 <<
"The number of sub-list of nodes created from the shared\n"
13370 <<
"polyline with loops was (" << n_sub_list <<
").\n"
13371 <<
"We can only handle up to three sub-list of nodes\n";
13373 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
13379 if (n_sub_list == 1 && (left_node_pt != right_node_pt))
13387 output_sorted_nodes_pt = tmp_sub_nodes;
13389 output_boundary_element_pt = tmp_sub_bnd_ele_pt;
13391 output_face_index_element = tmp_sub_face_idx_ele;
13397 if (input_connect_to_the_left == -2)
13399 std::stringstream error_message;
13401 <<
"The connection flag to the left (" << input_connect_to_the_left
13402 <<
") indicates a connection\n"
13403 <<
"with the same polyline.\n However, only one sub-polyline was "
13404 <<
"found and no loop\nwas identified\n\n";
13406 OOMPH_CURRENT_FUNCTION,
13407 OOMPH_EXCEPTION_LOCATION);
13412 if (input_connect_to_the_left == -3)
13414 output_connect_to_the_left.push_back(-1);
13418 output_connect_to_the_left.push_back(input_connect_to_the_left);
13422 if (input_connect_to_the_right == -2)
13424 std::stringstream error_message;
13426 <<
"The connection flag to the right (" << input_connect_to_the_right
13427 <<
") indicates a connection\n"
13428 <<
"with the same polyline.\n However, only one sub-polyline was "
13429 <<
"found and no loop\nwas identified\n\n";
13431 error_message.str(),
13432 "TriangleMesh::break_loops_on_shared_polyline_helper()",
13433 OOMPH_EXCEPTION_LOCATION);
13438 if (input_connect_to_the_right == -3)
13440 output_connect_to_the_right.push_back(-1);
13444 output_connect_to_the_right.push_back(input_connect_to_the_right);
13452 unsigned tmp_shd_bnd_id = initial_shd_bnd_id;
13460 Node* left_sub_node_pt = tmp_sub_nodes[0].front();
13461 Node* right_sub_node_pt = tmp_sub_nodes[0].back();
13464 if (left_sub_node_pt == right_sub_node_pt)
13470 std::list<Node*> first_half_node_pt;
13471 std::list<Node*> second_half_node_pt;
13480 const unsigned n_sub_nodes = tmp_sub_nodes[0].size();
13484 const unsigned n_sub_nodes_half =
13485 static_cast<unsigned>(n_sub_nodes / 2.0);
13490 std::list<Node*>::iterator it_sub = tmp_sub_nodes[0].begin();
13493 first_half_node_pt.push_back(*it_sub);
13499 unsigned counter_nodes = 0;
13500 unsigned counter2 = 0;
13503 for (; it_sub != tmp_sub_nodes[0].end(); it_sub++)
13506 first_half_node_pt.push_back(*it_sub);
13509 first_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[0][counter2]);
13510 first_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[0][counter2 + 1]);
13512 first_half_face_idx.push_back(tmp_sub_face_idx_ele[0][counter2]);
13513 first_half_face_idx.push_back(tmp_sub_face_idx_ele[0][counter2 + 1]);
13521 if (counter_nodes == n_sub_nodes_half)
13532 second_half_node_pt.push_back(*it_sub);
13538 for (; it_sub != tmp_sub_nodes[0].end(); it_sub++)
13541 second_half_node_pt.push_back(*it_sub);
13544 second_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[0][counter2]);
13545 second_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[0][counter2 + 1]);
13547 second_half_face_idx.push_back(tmp_sub_face_idx_ele[0][counter2]);
13548 second_half_face_idx.push_back(tmp_sub_face_idx_ele[0][counter2 + 1]);
13556 output_sorted_nodes_pt.push_back(first_half_node_pt);
13557 output_sorted_nodes_pt.push_back(second_half_node_pt);
13560 output_boundary_element_pt.push_back(first_half_ele_pt);
13561 output_boundary_element_pt.push_back(second_half_ele_pt);
13564 output_face_index_element.push_back(first_half_face_idx);
13565 output_face_index_element.push_back(second_half_face_idx);
13576 if (input_connect_to_the_left == -3)
13579 output_connect_to_the_left.push_back(-1);
13582 else if (input_connect_to_the_left == -2)
13585 output_connect_to_the_left.push_back(-1);
13590 output_connect_to_the_left.push_back(input_connect_to_the_left);
13596 output_connect_to_the_right.push_back(-1);
13607 output_connect_to_the_left.push_back(tmp_shd_bnd_id - 1);
13613 if (n_sub_list == 1)
13615 if (input_connect_to_the_right == -3)
13618 output_connect_to_the_right.push_back(tmp_shd_bnd_id - 1);
13620 else if (input_connect_to_the_right == -2)
13623 output_connect_to_the_right.push_back(tmp_shd_bnd_id - 1);
13625 else if (input_connect_to_the_right == -1)
13628 output_connect_to_the_right.push_back(tmp_shd_bnd_id - 1);
13633 output_connect_to_the_right.push_back(input_connect_to_the_right);
13639 output_connect_to_the_right.push_back(tmp_shd_bnd_id - 1);
13652 output_sorted_nodes_pt.push_back(tmp_sub_nodes[0]);
13655 output_boundary_element_pt.push_back(tmp_sub_bnd_ele_pt[0]);
13658 output_face_index_element.push_back(tmp_sub_face_idx_ele[0]);
13666 if (input_connect_to_the_left == -3)
13669 output_connect_to_the_left.push_back(-1);
13672 else if (input_connect_to_the_left == -2)
13675 output_connect_to_the_left.push_back(tmp_shd_bnd_id + 1);
13680 output_connect_to_the_left.push_back(input_connect_to_the_left);
13686 output_connect_to_the_right.push_back(tmp_shd_bnd_id + 1);
13694 if (n_sub_list > 1)
13698 left_sub_node_pt = tmp_sub_nodes[1].front();
13699 right_sub_node_pt = tmp_sub_nodes[1].back();
13702 if (left_sub_node_pt == right_sub_node_pt)
13708 std::list<Node*> first_half_node_pt;
13709 std::list<Node*> second_half_node_pt;
13718 const unsigned n_sub_nodes = tmp_sub_nodes[1].size();
13722 const unsigned n_sub_nodes_half =
13723 static_cast<unsigned>(n_sub_nodes / 2.0);
13728 std::list<Node*>::iterator it_sub = tmp_sub_nodes[1].begin();
13731 first_half_node_pt.push_back(*it_sub);
13737 unsigned counter_nodes = 0;
13738 unsigned counter2 = 0;
13741 for (; it_sub != tmp_sub_nodes[1].end(); it_sub++)
13744 first_half_node_pt.push_back(*it_sub);
13746 first_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[1][counter2]);
13747 first_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[1][counter2 + 1]);
13749 first_half_face_idx.push_back(tmp_sub_face_idx_ele[1][counter2]);
13750 first_half_face_idx.push_back(tmp_sub_face_idx_ele[1][counter2 + 1]);
13758 if (counter_nodes == n_sub_nodes_half)
13769 second_half_node_pt.push_back(*it_sub);
13775 for (; it_sub != tmp_sub_nodes[1].end(); it_sub++)
13778 second_half_node_pt.push_back(*it_sub);
13780 second_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[1][counter2]);
13781 second_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[1][counter2 + 1]);
13783 second_half_face_idx.push_back(tmp_sub_face_idx_ele[1][counter2]);
13784 second_half_face_idx.push_back(tmp_sub_face_idx_ele[1][counter2 + 1]);
13792 output_sorted_nodes_pt.push_back(first_half_node_pt);
13793 output_sorted_nodes_pt.push_back(second_half_node_pt);
13796 output_boundary_element_pt.push_back(first_half_ele_pt);
13797 output_boundary_element_pt.push_back(second_half_ele_pt);
13800 output_face_index_element.push_back(first_half_face_idx);
13801 output_face_index_element.push_back(second_half_face_idx);
13812 output_connect_to_the_left.push_back(tmp_shd_bnd_id - 1);
13817 output_connect_to_the_right.push_back(-1);
13828 output_connect_to_the_left.push_back(tmp_shd_bnd_id - 1);
13834 if (n_sub_list == 2)
13837 if (input_connect_to_the_right == -1)
13840 output_connect_to_the_right.push_back(tmp_shd_bnd_id - 1);
13843 else if (input_connect_to_the_right == -2)
13846 output_connect_to_the_right.push_back(tmp_shd_bnd_id - 1);
13849 else if (input_connect_to_the_right == -3)
13852 output_connect_to_the_right.push_back(tmp_shd_bnd_id - 1);
13857 output_connect_to_the_right.push_back(input_connect_to_the_right);
13867 std::stringstream error_message;
13869 <<
"The second sub-list of nodes creates a loop but this is not\n"
13870 <<
"the last list of sub-nodes.\n"
13871 <<
"This configuration is not supported\n";
13873 error_message.str(),
13874 "TriangleMesh::break_loops_on_shared_polyline_helper()",
13875 OOMPH_EXCEPTION_LOCATION);
13886 output_sorted_nodes_pt.push_back(tmp_sub_nodes[1]);
13889 output_boundary_element_pt.push_back(tmp_sub_bnd_ele_pt[1]);
13892 output_face_index_element.push_back(tmp_sub_face_idx_ele[1]);
13900 output_connect_to_the_left.push_back(tmp_shd_bnd_id - 1);
13906 if (n_sub_list == 2)
13909 if (input_connect_to_the_right == -3)
13912 output_connect_to_the_right.push_back(-1);
13916 else if (input_connect_to_the_right == -2)
13918 std::stringstream error_message;
13920 <<
"The connection flag to the right ("
13921 << input_connect_to_the_right <<
") indicates a connection\n"
13922 <<
"with the same polyline.\n However, the second sub-list of\n"
13923 <<
"nodes was found not making a loop so no connection with\n"
13924 <<
"itself should be marked\n\n";
13926 error_message.str(),
13927 "TriangleMesh::break_loops_on_shared_polyline_helper()",
13928 OOMPH_EXCEPTION_LOCATION);
13934 output_connect_to_the_right.push_back(input_connect_to_the_right);
13940 output_connect_to_the_right.push_back(tmp_shd_bnd_id + 1);
13951 if (n_sub_list > 2)
13955 left_sub_node_pt = tmp_sub_nodes[2].front();
13956 right_sub_node_pt = tmp_sub_nodes[2].back();
13959 if (left_sub_node_pt == right_sub_node_pt)
13965 std::list<Node*> first_half_node_pt;
13966 std::list<Node*> second_half_node_pt;
13975 const unsigned n_sub_nodes = tmp_sub_nodes[2].size();
13979 const unsigned n_sub_nodes_half =
13980 static_cast<unsigned>(n_sub_nodes / 2.0);
13985 std::list<Node*>::iterator it_sub = tmp_sub_nodes[2].begin();
13988 first_half_node_pt.push_back(*it_sub);
13994 unsigned counter_nodes = 0;
13995 unsigned counter2 = 0;
13998 for (; it_sub != tmp_sub_nodes[2].end(); it_sub++)
14001 first_half_node_pt.push_back(*it_sub);
14003 first_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[2][counter2]);
14004 first_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[2][counter2 + 1]);
14006 first_half_face_idx.push_back(tmp_sub_face_idx_ele[2][counter2]);
14007 first_half_face_idx.push_back(tmp_sub_face_idx_ele[2][counter2 + 1]);
14015 if (counter_nodes == n_sub_nodes_half)
14026 second_half_node_pt.push_back(*it_sub);
14032 for (; it_sub != tmp_sub_nodes[2].end(); it_sub++)
14035 second_half_node_pt.push_back(*it_sub);
14037 second_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[2][counter2]);
14038 second_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[2][counter2 + 1]);
14040 second_half_face_idx.push_back(tmp_sub_face_idx_ele[2][counter2]);
14041 second_half_face_idx.push_back(tmp_sub_face_idx_ele[2][counter2 + 1]);
14049 output_sorted_nodes_pt.push_back(first_half_node_pt);
14050 output_sorted_nodes_pt.push_back(second_half_node_pt);
14053 output_boundary_element_pt.push_back(first_half_ele_pt);
14054 output_boundary_element_pt.push_back(second_half_ele_pt);
14057 output_face_index_element.push_back(first_half_face_idx);
14058 output_face_index_element.push_back(second_half_face_idx);
14066 output_connect_to_the_left.push_back(tmp_shd_bnd_id - 1);
14071 output_connect_to_the_right.push_back(-1);
14082 output_connect_to_the_left.push_back(tmp_shd_bnd_id - 1);
14086 if (input_connect_to_the_right == -3)
14089 output_connect_to_the_right.push_back(tmp_shd_bnd_id - 1);
14091 else if (input_connect_to_the_right == -2)
14094 output_connect_to_the_right.push_back(tmp_shd_bnd_id - 1);
14096 else if (input_connect_to_the_right == -1)
14099 output_connect_to_the_right.push_back(tmp_shd_bnd_id - 1);
14104 output_connect_to_the_right.push_back(input_connect_to_the_right);
14117 output_sorted_nodes_pt.push_back(tmp_sub_nodes[2]);
14120 output_boundary_element_pt.push_back(tmp_sub_bnd_ele_pt[2]);
14123 output_face_index_element.push_back(tmp_sub_face_idx_ele[2]);
14131 output_connect_to_the_left.push_back(tmp_shd_bnd_id - 1);
14136 if (input_connect_to_the_right == -3)
14138 std::stringstream error_message;
14140 <<
"The connection flag to the right ("
14141 << input_connect_to_the_right <<
") indicates 'no connection and\n"
14142 <<
"stop adding nodes'.\n However, the thrid sub-list of\n"
14143 <<
"nodes must have a connection to the right with the same\n"
14144 <<
"shared polyline or with any other polyline\n\n";
14146 error_message.str(),
14147 "TriangleMesh::break_loops_on_shared_polyline_helper()",
14148 OOMPH_EXCEPTION_LOCATION);
14150 else if (input_connect_to_the_right == -1)
14152 std::stringstream error_message;
14154 <<
"The connection flag to the right ("
14155 << input_connect_to_the_right <<
") indicates 'no connection.\n"
14156 <<
"However, the thrid sub-list of nodes must have a connection\n"
14157 <<
"to the right with the same shared polyline or with any other\n"
14160 error_message.str(),
14161 "TriangleMesh::break_loops_on_shared_polyline_helper()",
14162 OOMPH_EXCEPTION_LOCATION);
14165 else if (input_connect_to_the_right == -2)
14168 output_connect_to_the_right.push_back(tmp_shd_bnd_id - 1);
14173 output_connect_to_the_right.push_back(input_connect_to_the_right);
14188 template<
class ELEMENT>
14191 const unsigned& initial_shd_bnd_id,
14192 std::list<Node*>& input_nodes,
14196 const int& input_connect_to_the_left,
14197 const int& input_connect_to_the_right,
14198 Vector<std::list<Node*>>& output_sorted_nodes_pt,
14206 Node* left_node_pt = input_nodes.front();
14207 Node* right_node_pt = input_nodes.back();
14217 std::list<Node*>::iterator it = input_nodes.begin();
14220 unsigned counter = 0;
14223 while (it != input_nodes.end())
14228 if (it == input_nodes.end())
14240 std::list<Node*> sub_nodes;
14252 sub_nodes.push_back(*it);
14262 sub_nodes.push_back((*it));
14265 sub_bnd_ele_pt.push_back(input_boundary_element_pt[counter]);
14268 sub_bnd_face_ele_pt.push_back(input_boundary_face_element_pt[counter]);
14271 sub_face_idx_ele.push_back(input_face_index_element[counter]);
14278 }
while ((*it) != left_node_pt && (*it) != right_node_pt &&
14279 it != input_nodes.end());
14282 tmp_sub_nodes.push_back(sub_nodes);
14285 tmp_sub_bnd_ele_pt.push_back(sub_bnd_ele_pt);
14287 tmp_sub_bnd_face_ele_pt.push_back(sub_bnd_face_ele_pt);
14289 tmp_sub_face_idx_ele.push_back(sub_face_idx_ele);
14297 const unsigned n_sub_list = tmp_sub_nodes.size();
14300 if (n_sub_list > 1)
14302 std::stringstream error_message;
14304 <<
"The number of sub-list of nodes created from the shared\n"
14305 <<
"polyline with loops was (" << n_sub_list <<
").\n"
14306 <<
"We can only handle one list which may still contain loops\n"
14307 <<
"(or repeated nodes)\n";
14309 error_message.str(),
14310 "TriangleMesh::break_loops_on_shared_polyline_load_balance_helper()",
14311 OOMPH_EXCEPTION_LOCATION);
14317 if (n_sub_list == 1 && (left_node_pt != right_node_pt))
14325 output_sorted_nodes_pt = tmp_sub_nodes;
14327 output_boundary_element_pt = tmp_sub_bnd_ele_pt;
14329 output_boundary_face_element_pt = tmp_sub_bnd_face_ele_pt;
14331 output_face_index_element = tmp_sub_face_idx_ele;
14337 if (input_connect_to_the_left == -2)
14339 std::stringstream error_message;
14341 <<
"The connection flag to the left (" << input_connect_to_the_left
14342 <<
") indicates a connection\n"
14343 <<
"with the same polyline.\n However, only one sub-polyline was "
14344 <<
"found and no loops\nwere identified\n\n";
14346 error_message.str(),
14347 "TriangleMesh::break_loops_on_shared_polyline_load_balance_helper()",
14348 OOMPH_EXCEPTION_LOCATION);
14353 if (input_connect_to_the_left == -3)
14355 output_connect_to_the_left.push_back(-1);
14359 output_connect_to_the_left.push_back(input_connect_to_the_left);
14363 if (input_connect_to_the_right == -2)
14365 std::stringstream error_message;
14367 <<
"The connection flag to the right (" << input_connect_to_the_right
14368 <<
") indicates a connection\n"
14369 <<
"with the same polyline.\n However, only one sub-polyline was "
14370 <<
"found and no loops\nwere identified\n\n";
14372 error_message.str(),
14373 "TriangleMesh::break_loops_on_shared_polyline_load_balance_helper()",
14374 OOMPH_EXCEPTION_LOCATION);
14379 if (input_connect_to_the_right == -3)
14381 output_connect_to_the_right.push_back(-1);
14385 output_connect_to_the_right.push_back(input_connect_to_the_right);
14393 unsigned tmp_shd_bnd_id = initial_shd_bnd_id;
14401 Node* left_sub_node_pt = tmp_sub_nodes[0].front();
14402 Node* right_sub_node_pt = tmp_sub_nodes[0].back();
14405 if (left_sub_node_pt == right_sub_node_pt)
14411 std::list<Node*> first_half_node_pt;
14412 std::list<Node*> second_half_node_pt;
14424 const unsigned n_sub_nodes = tmp_sub_nodes[0].size();
14428 const unsigned n_sub_nodes_half =
14429 static_cast<unsigned>(n_sub_nodes / 2.0);
14434 std::list<Node*>::iterator it_sub = tmp_sub_nodes[0].begin();
14437 first_half_node_pt.push_back(*it_sub);
14443 unsigned counter_nodes = 0;
14444 unsigned counter2 = 0;
14447 for (; it_sub != tmp_sub_nodes[0].end(); it_sub++)
14450 first_half_node_pt.push_back(*it_sub);
14453 first_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[0][counter2]);
14455 first_half_ele_face_pt.push_back(tmp_sub_bnd_face_ele_pt[0][counter2]);
14457 first_half_face_idx.push_back(tmp_sub_face_idx_ele[0][counter2]);
14465 if (counter_nodes == n_sub_nodes_half)
14476 second_half_node_pt.push_back(*it_sub);
14482 for (; it_sub != tmp_sub_nodes[0].end(); it_sub++)
14485 second_half_node_pt.push_back(*it_sub);
14488 second_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[0][counter2]);
14490 second_half_ele_face_pt.push_back(tmp_sub_bnd_face_ele_pt[0][counter2]);
14492 second_half_face_idx.push_back(tmp_sub_face_idx_ele[0][counter2]);
14500 output_sorted_nodes_pt.push_back(first_half_node_pt);
14501 output_sorted_nodes_pt.push_back(second_half_node_pt);
14504 output_boundary_element_pt.push_back(first_half_ele_pt);
14505 output_boundary_element_pt.push_back(second_half_ele_pt);
14508 output_boundary_face_element_pt.push_back(first_half_ele_face_pt);
14509 output_boundary_face_element_pt.push_back(second_half_ele_face_pt);
14512 output_face_index_element.push_back(first_half_face_idx);
14513 output_face_index_element.push_back(second_half_face_idx);
14524 if (input_connect_to_the_left == -3)
14527 output_connect_to_the_left.push_back(-1);
14530 else if (input_connect_to_the_left == -2)
14533 output_connect_to_the_left.push_back(-1);
14538 output_connect_to_the_left.push_back(input_connect_to_the_left);
14544 output_connect_to_the_right.push_back(-1);
14555 output_connect_to_the_left.push_back(tmp_shd_bnd_id - 1);
14561 if (n_sub_list == 1)
14563 if (input_connect_to_the_right == -3)
14566 output_connect_to_the_right.push_back(tmp_shd_bnd_id - 1);
14568 else if (input_connect_to_the_right == -2)
14571 output_connect_to_the_right.push_back(tmp_shd_bnd_id - 1);
14573 else if (input_connect_to_the_right == -1)
14576 output_connect_to_the_right.push_back(tmp_shd_bnd_id - 1);
14581 output_connect_to_the_right.push_back(input_connect_to_the_right);
14587 output_connect_to_the_right.push_back(tmp_shd_bnd_id - 1);
14597 std::stringstream error_message;
14599 <<
"The initial and final node in the current shared polyline are not\n"
14600 <<
"the same and the number of sublists is (" << n_sub_list <<
").\n"
14601 <<
"We can not handle more than one sublist in the method to break\n"
14602 <<
"loops at the load balance stage\n\n";
14604 error_message.str(),
14605 "TriangleMesh::break_loops_on_shared_polyline_load_balance_helper()",
14606 OOMPH_EXCEPTION_LOCATION);
14616 template<
class ELEMENT>
14618 const unsigned& my_rank,
14619 const unsigned& shd_bnd_id,
14620 const unsigned& iproc,
14621 const unsigned& jproc,
14622 std::list<Node*>& sorted_nodes,
14623 const int& root_edge_bnd_id,
14627 const int& connect_to_the_left_flag,
14628 const int& connect_to_the_right_flag)
14639 Shared_boundaries_ids[iproc][jproc].push_back(shd_bnd_id);
14642 Shared_boundaries_ids[jproc][iproc].push_back(shd_bnd_id);
14647 processors[0] = iproc;
14648 processors[1] = jproc;
14649 Shared_boundary_from_processors[shd_bnd_id] = processors;
14655 if (iproc == my_rank || jproc == my_rank)
14662 const unsigned n_nodes = sorted_nodes.size();
14667 unsigned counter = 0;
14669 for (std::list<Node*>::iterator it = sorted_nodes.begin();
14670 it != sorted_nodes.end();
14673 vertices[counter].resize(2);
14674 vertices[counter][0] = (*it)->x(0);
14675 vertices[counter][1] = (*it)->x(1);
14691 if (root_edge_bnd_id != -1)
14695 Shared_boundary_overlaps_internal_boundary[shd_bnd_id] =
14696 static_cast<unsigned>(root_edge_bnd_id);
14704 const unsigned n_shared_boundary_elements = bulk_bnd_ele_pt.size();
14708 const unsigned n_face_index = face_index_ele.size();
14709 if (n_shared_boundary_elements != n_face_index)
14711 std::ostringstream error_message;
14713 <<
"The number of shared boundary elements is different from the\n"
14714 <<
"number of face indexes associated to the shared boundary\n"
14716 <<
"Number of shared boundary elements: ("
14717 << n_shared_boundary_elements <<
")\n"
14718 <<
"Number of face indexes: (" << n_face_index <<
")\n\n";
14720 "TriangleMesh::create_shared_polyline()",
14721 OOMPH_EXCEPTION_LOCATION);
14727 for (
unsigned i = 0;
i < n_shared_boundary_elements;
i++)
14729 add_shared_boundary_element(shd_bnd_id, bulk_bnd_ele_pt[
i]);
14730 add_face_index_at_shared_boundary(shd_bnd_id, face_index_ele[
i]);
14734 for (std::list<Node*>::iterator it = sorted_nodes.begin();
14735 it != sorted_nodes.end();
14738 add_shared_boundary_node(shd_bnd_id, (*it));
14746 this->Boundary_curve_section_pt[shd_bnd_id] = polyline_pt;
14751 const unsigned n_procs = unsorted_polylines_pt.size();
14756 unsorted_polylines_pt[iproc].push_back(polyline_pt);
14760 unsorted_polylines_pt[jproc].push_back(polyline_pt);
14766 unsorted_polylines_pt[0].push_back(polyline_pt);
14770 this->Free_curve_section_pt.insert(polyline_pt);
14780 if (connect_to_the_left_flag < 0)
14783 if (connect_to_the_left_flag != -1)
14785 std::ostringstream error_message;
14787 <<
"The only accepted values for the connection flags are:\n"
14788 <<
"POSITIVE values or -1, any other value is rejected, please\n"
14789 <<
"check that you previously called the methods to deal with\n"
14790 <<
"other flag values\n"
14791 <<
"The current flag value for connection to the left is: ("
14792 << connect_to_the_left_flag <<
")\n\n";
14794 "TriangleMesh::create_shared_polyline()",
14795 OOMPH_EXCEPTION_LOCATION);
14800 if (connect_to_the_right_flag < 0)
14803 if (connect_to_the_right_flag != -1)
14805 std::ostringstream error_message;
14807 <<
"The only accepted values for the connection flags are:\n"
14808 <<
"POSITIVE values or -1, any other value is rejected, please\n"
14809 <<
"check that you previously called the methods to deal with\n"
14810 <<
"other flag values\n"
14811 <<
"The current flag value for connection to the right is: ("
14812 << connect_to_the_right_flag <<
")\n\n";
14814 "TriangleMesh::create_shared_polyline()",
14815 OOMPH_EXCEPTION_LOCATION);
14821 if (connect_to_the_left_flag != -1)
14824 const unsigned bnd_id_connection_to_the_left =
14825 static_cast<unsigned>(connect_to_the_left_flag);
14830 bnd_id_connection_to_the_left;
14837 if (connect_to_the_right_flag != -1)
14840 const unsigned bnd_id_connection_to_the_right =
14841 static_cast<unsigned>(connect_to_the_right_flag);
14846 bnd_id_connection_to_the_right;
14859 template<
class ELEMENT>
14866 const unsigned nbound = this->nboundary();
14869 const unsigned n_regions = this->nregion();
14872 for (
unsigned b = 0; b < nbound; b++)
14877 const unsigned nbound_ele = this->nboundary_element(b);
14880 Vector<int> backed_up_face_index_at_boundary(nbound_ele);
14881 for (
unsigned e = 0;
e < nbound_ele;
e++)
14884 backed_up_boundary_element_pt[
e] = this->boundary_element_pt(b,
e);
14886 backed_up_face_index_at_boundary[
e] =
14887 this->face_index_at_boundary(b,
e);
14897 for (
unsigned ir = 0; ir < n_regions; ir++)
14900 const unsigned region_id =
14901 static_cast<unsigned>(this->region_attribute(ir));
14903 const unsigned nbnd_region_ele =
14904 this->nboundary_element_in_region(b, region_id);
14907 for (
unsigned e = 0;
e < nbnd_region_ele;
e++)
14910 backed_up_boundary_region_element_pt[ir][
e] =
14911 this->boundary_element_in_region_pt(b, region_id,
e);
14914 backed_up_face_index_at_boundary_region[ir][
e] =
14915 this->face_index_at_boundary_in_region(b, region_id,
e);
14921 this->Boundary_element_pt[b].clear();
14922 this->Face_index_at_boundary[b].clear();
14925 this->Boundary_region_element_pt[b].clear();
14926 this->Face_index_region_at_boundary[b].clear();
14935 const unsigned nold_bnd_ele = ntmp_boundary_elements[b];
14937 for (
unsigned e = 0;
e < nold_bnd_ele;
e++)
14942 deleted_elements.begin(), deleted_elements.end(), tmp_ele_pt);
14945 if (it == deleted_elements.end())
14948 this->Boundary_element_pt[b].push_back(add_ele_pt);
14949 const int face_index = backed_up_face_index_at_boundary[
e];
14950 this->Face_index_at_boundary[b].push_back(face_index);
14958 for (
unsigned ir = 0; ir < n_regions; ir++)
14961 const unsigned region_id =
14962 static_cast<unsigned>(this->region_attribute(ir));
14965 const unsigned nold_bnd_region_ele =
14966 ntmp_boundary_elements_in_region[b][ir];
14970 for (
unsigned e = 0;
e < nold_bnd_region_ele;
e++)
14974 backed_up_boundary_region_element_pt[ir][
e];
14977 deleted_elements.begin(), deleted_elements.end(), tmp_ele_pt);
14980 if (it == deleted_elements.end())
14983 backed_up_boundary_region_element_pt[ir][
e];
14984 this->Boundary_region_element_pt[b][region_id].push_back(
14986 const int face_index =
14987 backed_up_face_index_at_boundary_region[ir][
e];
14988 this->Face_index_region_at_boundary[b][region_id].push_back(
15001 for (
unsigned e = nold_bnd_ele;
e < nbound_ele;
e++)
15004 this->Boundary_element_pt[b].push_back(add_ele_pt);
15005 const int face_index = backed_up_face_index_at_boundary[
e];
15006 this->Face_index_at_boundary[b].push_back(face_index);
15012 for (
unsigned ir = 0; ir < n_regions; ir++)
15015 const unsigned region_id =
15016 static_cast<unsigned>(this->region_attribute(ir));
15019 const unsigned nold_bnd_region_ele =
15020 ntmp_boundary_elements_in_region[b][ir];
15023 const unsigned nbnd_region_ele =
15024 this->nboundary_element_in_region(b, region_id);
15028 for (
unsigned e = nold_bnd_region_ele;
e < nbnd_region_ele;
e++)
15031 backed_up_boundary_region_element_pt[ir][
e];
15032 this->Boundary_region_element_pt[b][region_id].push_back(add_ele_pt);
15033 const int face_index = backed_up_face_index_at_boundary_region[ir][
e];
15034 this->Face_index_region_at_boundary[b][region_id].push_back(
15043 Lookup_for_elements_next_boundary_is_setup =
true;
15048#ifdef OOMPH_HAS_TRIANGLE_LIB
15053 template<
class ELEMENT>
15072 (
double*)malloc(triangulate_io.
numberofpoints * 2 *
sizeof(
double));
15085 for (
unsigned count_point = 0; count_point < n_points * 2; count_point++)
15087 triangle_refine.
pointlist[count_point] =
15092 if (count_point % 2 == 0)
15094 x_coord[count_point / 2] = triangulate_io.
pointlist[count_point];
15098 y_coord[(count_point - 1) / 2] = triangulate_io.
pointlist[count_point];
15103 for (
unsigned count_marker = 0; count_marker < n_points; count_marker++)
15110 for (
unsigned count_seg = 0; count_seg < n_segments * 2; count_seg++)
15117 for (
unsigned count_markers = 0; count_markers < n_segments;
15129 (
double*)malloc(triangulate_io.
numberofholes * 2 *
sizeof(
double));
15132 for (
unsigned count_hole = 0; count_hole < n_holes * 2; count_hole++)
15134 triangle_refine.
holelist[count_hole] =
15135 triangulate_io.
holelist[count_hole];
15143 if (n_triangles != target_area.size())
15145 std::stringstream err;
15146 err <<
"Number of triangles in triangulate_io=" << n_triangles
15147 <<
" doesn't match\n"
15148 <<
"size of target area vector (" << target_area.size() <<
")\n";
15150 err.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
15161 for (
unsigned count_tri = 0; count_tri < n_triangles * 3; count_tri++)
15170 for (
unsigned count_area = 0; count_area < n_triangles; count_area++)
15182 for (
unsigned count_attribute = 0;
15192#ifdef OOMPH_HAS_MPI
15206 const std::pair<double, double>& rhs)
const
15208 double diff_y = lhs.second - rhs.second;
15219 double diff_x = lhs.first - rhs.first;
15220 if (fabs(diff_x) <
Tol)
15222 std::ostringstream warning_message;
15224 <<
"Dodgy \"lower left\" (lexicographic) comparison "
15225 <<
"of points with cooordinates: "
15226 <<
" lhs = ( " << lhs.first <<
" , " << lhs.second <<
" ) \n"
15227 <<
" rhs = ( " << rhs.first <<
" , " << rhs.second <<
" ) \n"
15228 <<
"x and y coordinates differ by less than tolerance!\n"
15229 <<
"diff_x = " << diff_x <<
"\n"
15230 <<
"diff_y = " << diff_y <<
"\n"
15231 <<
"Tol = " <<
Tol <<
"\n";
15233 OOMPH_CURRENT_FUNCTION,
15234 OOMPH_EXCEPTION_LOCATION);
15237 if (lhs.first < rhs.first)
15291 template<
class ELEMENT>
15296 this->shared_boundaries_in_this_processor(my_rank_shared_boundaries_ids);
15299 const unsigned nmy_rank_shd_bnd = my_rank_shared_boundaries_ids.size();
15302 for (
unsigned i = 0;
i < nmy_rank_shd_bnd;
i++)
15307 std::map<std::pair<double, double>, Node*,
classcomp> sorted_nodes_pt;
15314 double min_distance_squared = DBL_MAX;
15319 const unsigned b = my_rank_shared_boundaries_ids[
i];
15322 const unsigned nbnd_node = this->nshared_boundary_node(b);
15326 for (
unsigned i_node = 0; i_node < nbnd_node; i_node++)
15328 Node* node_pt = this->shared_boundary_node_pt(b, i_node);
15329 std::pair<double, double> vertex =
15330 std::make_pair(node_pt->x(0), node_pt->x(1));
15331 sorted_nodes_pt[vertex] = node_pt;
15337 for (
unsigned j_node = 0; j_node < nbnd_node; j_node++)
15339 if (i_node != j_node)
15341 Node* node2_pt = this->shared_boundary_node_pt(b, j_node);
15344 double squared_distance = 0.0;
15345 for (
unsigned ii = 0; ii < 2; ii++)
15347 squared_distance += (node_pt->x(ii) - node2_pt->x(ii)) *
15348 (node_pt->x(ii) - node2_pt->x(ii));
15350 if (squared_distance < min_distance_squared)
15352 min_distance_squared = squared_distance;
15359 std::ostringstream warning_message;
15360 warning_message <<
"Minimum distance between nodes on boundary " << b
15362 <<
"is " << sqrt(min_distance_squared)
15363 <<
" which is less than "
15364 <<
"Bottom_left_sorter.Tol = "
15366 <<
"This may screw up the ordering of the nodes on "
15367 "shared boundaries\n";
15369 OOMPH_CURRENT_FUNCTION,
15370 OOMPH_EXCEPTION_LOCATION);
15376 unsigned counter = 0;
15378 this->Sorted_shared_boundary_node_pt[b].resize(nbnd_node);
15384 for (std::map<std::pair<double, double>, Node*>::iterator it_map =
15385 sorted_nodes_pt.begin();
15386 it_map != sorted_nodes_pt.end();
15390 this->Sorted_shared_boundary_node_pt[b][counter++] = (*it_map).second;
15401 template<
class ELEMENT>
15404 const bool update_elements,
15405 const bool flush_nodes,
15406 const bool update_nodes)
15409 const unsigned my_rank = this->communicator_pt()->my_rank();
15415 const unsigned initial_id = this->initial_shared_boundary_id();
15418 const unsigned final_id = this->final_shared_boundary_id();
15420 if (flush_elements)
15423 this->flush_shared_boundary_element();
15425 this->flush_face_index_at_shared_boundary();
15431 this->flush_shared_boundary_node();
15434 for (
unsigned b = initial_id; b < final_id; b++)
15438 procs_from_shrd_bnd = this->shared_boundary_from_processors(b);
15439 bool current_processor_has_b_boundary =
false;
15440 const unsigned n_procs_from_shrd_bnd = procs_from_shrd_bnd.size();
15441 for (
unsigned p = 0; p < n_procs_from_shrd_bnd; p++)
15443 if (procs_from_shrd_bnd[p] == my_rank)
15445 current_processor_has_b_boundary =
true;
15450 if (current_processor_has_b_boundary)
15452 if (update_elements)
15454 const unsigned nboundary_ele = this->nboundary_element(b);
15455 for (
unsigned e = 0;
e < nboundary_ele;
e++)
15460 this->add_shared_boundary_element(b, bnd_ele_pt);
15462 int face_index = this->face_index_at_boundary(b,
e);
15463 this->add_face_index_at_shared_boundary(b, face_index);
15469 const unsigned nboundary_node = this->nboundary_node(b);
15470 for (
unsigned n = 0; n < nboundary_node; n++)
15472 Node* bnd_node_pt = this->boundary_node_pt(b, n);
15473 this->add_shared_boundary_node(b, bnd_node_pt);
15485 template<
class ELEMENT>
15489 unsigned nproc = this->communicator_pt()->nproc();
15491 unsigned my_rank = this->communicator_pt()->my_rank();
15494 double tt_start = 0.0;
15495 double tt_end = 0.0;
15509 other_proc_shd_bnd_node_pt(nproc);
15511 for (
unsigned iproc = 0; iproc < nproc; iproc++)
15514 other_proc_shd_bnd_node_pt[iproc].resize(nproc);
15515 for (
unsigned jproc = 0; jproc < nproc; jproc++)
15518 const unsigned initial_shd_bnd_id = this->initial_shared_boundary_id();
15519 const unsigned final_shd_bnd_id = this->final_shared_boundary_id();
15520 const unsigned nshared_bound = final_shd_bnd_id - initial_shd_bnd_id;
15521 other_proc_shd_bnd_node_pt[iproc][jproc].resize(nshared_bound);
15534 std::map<Vector<unsigned>,
unsigned> node_name_to_global_index;
15546 compute_global_node_names_and_shared_nodes(other_proc_shd_bnd_node_pt,
15548 node_name_to_global_index,
15549 global_shared_node_pt);
15552 const unsigned n_ele = this->nelement();
15554 if (Print_timings_level_adaptation > 1)
15558 double t_final_global_node_names_and_shared_nodes =
15560 oomph_info <<
"CPU for computing global node names and shared nodes "
15561 <<
"[n_ele=" << n_ele
15562 <<
"]: " << t_final_global_node_names_and_shared_nodes
15580 double t_start_send_info_shd_nodes_on_original_bnds =
15585 send_boundary_node_info_of_shared_nodes(
15586 global_node_names, node_name_to_global_index, global_shared_node_pt);
15588 if (Print_timings_level_adaptation > 1)
15593 <<
"CPU for sending info. of shared nodes on original boundaries: "
15622 for (
unsigned iproc = 0; iproc < nproc; iproc++)
15624 const unsigned n_shd_bnd_iproc = this->nshared_boundaries(my_rank, iproc);
15625 ele_with_node_on_shd_bnd_pt[iproc].resize(n_shd_bnd_iproc);
15632 for (
unsigned e = 0;
e < n_ele;
e++)
15637 const unsigned n_nodes = ele_pt->
nnode();
15640 for (
unsigned n = 0; n < n_nodes; n++)
15643 Node* node_pt = ele_pt->
node_pt(n);
15649 for (
unsigned iproc = 0; iproc < nproc; iproc++)
15654 const unsigned n_shd_bnd_iproc =
15655 this->nshared_boundaries(my_rank, iproc);
15658 if (iproc != my_rank && n_shd_bnd_iproc > 0)
15663 this->shared_boundaries_ids(my_rank, iproc);
15666 for (
unsigned isb = 0; isb < n_shd_bnd_iproc; isb++)
15668 const unsigned shd_bnd_id = shd_bnd_ids[isb];
15669 const unsigned n_ele_shd_bnd =
15670 this->nshared_boundary_element(shd_bnd_id);
15674 if (n_ele_shd_bnd > 0 &&
15675 this->is_node_on_shared_boundary(shd_bnd_id, node_pt))
15679 ele_with_node_on_shd_bnd_pt[iproc][isb].push_back(ele_pt);
15722 double t_start_regenerate_halo_ed_elements_nodes_first_stage =
15726 for (
unsigned iproc = 0; iproc < nproc; iproc++)
15729 if (iproc != my_rank)
15732 const unsigned nshared_boundaries_with_iproc =
15733 this->nshared_boundaries(my_rank, iproc);
15735 if (nshared_boundaries_with_iproc > 0)
15749#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
15755 bound_shared_with_iproc = this->shared_boundaries_ids(my_rank, iproc);
15758 for (
unsigned bs = 0; bs < nshared_boundaries_with_iproc; bs++)
15760 const unsigned bnd_id = bound_shared_with_iproc[bs];
15762 const unsigned nel_bnd = this->nshared_boundary_element(bnd_id);
15773 std::map<FiniteElement*, bool> already_added;
15776 for (
unsigned e = 0;
e < nel_bnd;
e++)
15780 this->shared_boundary_element_pt(bnd_id,
e);
15785 if (!already_added[ele_pt])
15788 haloed_element.push_back(ele_pt);
15790 already_added[ele_pt] =
true;
15801 const unsigned n_ele_with_node_on_shd_bnd =
15802 ele_with_node_on_shd_bnd_pt[iproc][bs].size();
15805 for (
unsigned iele = 0; iele < n_ele_with_node_on_shd_bnd; iele++)
15809 ele_with_node_on_shd_bnd_pt[iproc][bs][iele];
15811 if (!already_added[ele_pt])
15814 haloed_element.push_back(ele_pt);
15816 already_added[ele_pt] =
true;
15824 const unsigned nhaloed_ele = haloed_element.size();
15832#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
15833 std::stringstream junk;
15834 junk <<
"Number of haloed elements " << nhaloed_ele;
15839 for (
unsigned e = 0;
e < nhaloed_ele;
e++)
15843 const unsigned nroot_haloed_ele =
15844 this->nroot_haloed_element(iproc);
15849 const unsigned haloed_ele_index =
15850 this->try_to_add_root_haloed_element_pt(iproc, gen_ele_pt);
15854 if (nroot_haloed_ele == haloed_ele_index)
15857#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
15859 "Haloed element needs to be constructed");
15863 get_required_elemental_information_helper(iproc, ele_pt);
15866 const unsigned nnodes = ele_pt->
nnode();
15867 for (
unsigned j = 0; j < nnodes; j++)
15869 Node* node_pt = ele_pt->
node_pt(j);
15873 add_haloed_node_helper(iproc, node_pt);
15880#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
15882 "Haloed element already exists");
15885#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
15887 "Index of existing haloed element");
15901 int send_proc =
static_cast<int>(iproc);
15903 int recv_proc =
static_cast<int>(iproc);
15904 send_and_receive_elements_nodes_info(send_proc, recv_proc);
15917 for (
unsigned bs = 0; bs < nshared_boundaries_with_iproc; bs++)
15920 const unsigned nhaloed_ele =
15923#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
15926 <<
" Number of elements need to be constructed "
15932 for (
unsigned e = 0;
e < nhaloed_ele;
e++)
15936 create_halo_element(iproc,
15937 iproc_currently_created_nodes_pt[iproc],
15938 other_proc_shd_bnd_node_pt,
15940 node_name_to_global_index,
15941 global_shared_node_pt);
15953 if (Print_timings_level_adaptation > 1)
15956 double t_final_regenerate_halo_ed_elements_nodes_first_stage =
15958 t_start_regenerate_halo_ed_elements_nodes_first_stage;
15960 oomph_info <<
"CPU for re-generating halo(ed) elements/nodes "
15961 <<
"(first stage) [n_ele=" << n_ele <<
"]: "
15962 << t_final_regenerate_halo_ed_elements_nodes_first_stage
15979 double t_start_regenerate_halo_ed_elements_nodes_second_stage =
15984 reset_halo_haloed_scheme_helper(other_proc_shd_bnd_node_pt,
15985 iproc_currently_created_nodes_pt,
15987 node_name_to_global_index,
15988 global_shared_node_pt);
15990 if (Print_timings_level_adaptation > 1)
15993 double t_final_regenerate_halo_ed_elements_nodes_second_stage =
15995 t_start_regenerate_halo_ed_elements_nodes_second_stage;
15997 oomph_info <<
"CPU for re-generating halo(ed) elements/nodes "
15998 <<
"(second stage) [n_ele=" << n_ele <<
"]: "
15999 << t_final_regenerate_halo_ed_elements_nodes_second_stage
16011#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
16017 if (Print_timings_level_adaptation > 1)
16020 oomph_info <<
"CPU for resetting halo-haloed scheme (without "
16021 "classification of halo and haloed nodes): "
16022 << tt_end - tt_start << std::endl;
16028 const bool report_stats =
true;
16033 this->classify_halo_and_haloed_nodes(tmp_doc_info, report_stats);
16037 if (Print_timings_level_adaptation > 1)
16040 oomph_info <<
"CPU for resetting halo-haloed scheme (with classification "
16041 "of halo and haloed nodes): "
16042 << tt_end - tt_start << std::endl;
16059 template<
class ELEMENT>
16063 other_proc_shd_bnd_node_pt,
16069 const unsigned nproc = this->communicator_pt()->nproc();
16071 const unsigned my_rank = this->communicator_pt()->my_rank();
16083 unsigned counter_nodes = 0;
16085 std::map<Node*, bool> done_node;
16087 std::map<Node*, unsigned> local_node_number;
16108 for (
unsigned iproc = 0; iproc < nproc; iproc++)
16111 if (iproc != my_rank)
16114 const unsigned n_shd_bnds_with_iproc =
16115 this->nshared_boundaries(my_rank, iproc);
16119 this->shared_boundaries_ids(my_rank, iproc);
16122 for (
unsigned ishd = 0; ishd < n_shd_bnds_with_iproc; ishd++)
16125 std::map<Node*, bool> done_node_shd_bnd;
16127 unsigned shd_bnd_id = bnd_shd_with_iproc[ishd];
16129 const unsigned n_shd_bnd_ele =
16130 this->nshared_boundary_element(shd_bnd_id);
16133 for (
unsigned e = 0;
e < n_shd_bnd_ele;
e++)
16137 this->shared_boundary_element_pt(shd_bnd_id,
e);
16140 const unsigned n_nodes = ele_pt->
nnode();
16143 for (
unsigned n = 0; n < n_nodes; n++)
16146 Node* node_pt = ele_pt->
node_pt(n);
16151 if (!done_node_shd_bnd[node_pt] &&
16152 this->is_node_on_shared_boundary(shd_bnd_id, node_pt))
16155 done_node_shd_bnd[node_pt] =
true;
16160 const unsigned n_nodes_shd_bnd =
16161 nsorted_shared_boundary_node(shd_bnd_id);
16164 unsigned index = 0;
16168 bool found_node_on_shared_boundary =
false;
16172 for (
unsigned k = 0; k < n_nodes_shd_bnd; k++)
16175 Node* shd_bnd_node_pt =
16176 sorted_shared_boundary_node_pt(shd_bnd_id, k);
16179 if (shd_bnd_node_pt == node_pt)
16185 found_node_on_shared_boundary =
true;
16194 if (!found_node_on_shared_boundary)
16196 std::ostringstream error_message;
16197 error_message <<
"The index of the node on boundary ("
16198 << shd_bnd_id <<
") was not found.\n"
16199 <<
"These are the node coordinates\n"
16200 <<
"(" << node_pt->x(0) <<
"," << node_pt->x(1)
16203 OOMPH_CURRENT_FUNCTION,
16204 OOMPH_EXCEPTION_LOCATION);
16210 node_name[0] = my_rank;
16211 node_name[1] = iproc;
16212 node_name[2] = shd_bnd_id;
16213 node_name[3] = index;
16218 if (!done_node[node_pt])
16223 local_node_pt.push_back(node_pt);
16226 local_node_number[node_pt] = counter_nodes;
16228 node_name[4] = counter_nodes;
16232 done_node[node_pt] =
true;
16237 first_node_name[0] = node_name;
16238 local_node_names.push_back(first_node_name);
16245 unsigned node_number = local_node_number[node_pt];
16248 node_name[4] = node_number;
16252 local_node_names[node_number].push_back(node_name);
16277 unsigned n_total_local_names = 0;
16279 const unsigned n_local_nodes = local_node_names.size();
16282 for (
unsigned i = 0;
i < n_local_nodes;
i++)
16285 const unsigned n_inode_names = local_node_names[
i].size();
16287 n_total_local_names += n_inode_names;
16292 const unsigned n_info_per_node_name = 5;
16295 n_info_per_node_name);
16297 unsigned counter = 0;
16299 for (
unsigned i = 0;
i < n_local_nodes;
i++)
16302 const unsigned n_inode_names = local_node_names[
i].size();
16304 for (
unsigned j = 0; j < n_inode_names; j++)
16307 flat_packed_send_udata[counter++] = local_node_names[
i][j][0];
16309 flat_packed_send_udata[counter++] = local_node_names[
i][j][1];
16311 flat_packed_send_udata[counter++] = local_node_names[
i][j][2];
16313 flat_packed_send_udata[counter++] = local_node_names[
i][j][3];
16315 flat_packed_send_udata[counter++] = local_node_names[
i][j][4];
16325 const unsigned n_udata_send_to_root = flat_packed_send_udata.size();
16338 const unsigned root_processor = 0;
16346 MPI_Gather(&n_total_local_names,
16349 &root_n_names_per_processor[0],
16353 comm_pt->mpi_comm());
16357 unsigned root_n_total_udata_receive = 0;
16359 for (
unsigned iproc = 0; iproc < nproc; iproc++)
16361 root_n_udata_to_receive[iproc] =
16362 root_n_names_per_processor[iproc] * n_info_per_node_name;
16363 root_n_total_udata_receive += root_n_udata_to_receive[iproc];
16369 root_uoffsets_receive[0] = 0;
16370 for (
unsigned iproc = 1; iproc < nproc; iproc++)
16373 root_uoffsets_receive[iproc] =
16374 root_uoffsets_receive[iproc - 1] + root_n_udata_to_receive[iproc - 1];
16378 if (flat_packed_send_udata.size() == 0)
16380 flat_packed_send_udata.resize(1);
16384 Vector<unsigned> root_flat_packed_receive_udata(root_n_total_udata_receive);
16387 if (my_rank != root_processor)
16390 if (root_flat_packed_receive_udata.size() == 0)
16392 root_flat_packed_receive_udata.resize(1);
16397 MPI_Gatherv(&flat_packed_send_udata[0],
16400 n_udata_send_to_root,
16403 &root_flat_packed_receive_udata[0],
16407 &root_n_udata_to_receive[0],
16410 &root_uoffsets_receive[0],
16416 comm_pt->mpi_comm());
16419 flat_packed_send_udata.clear();
16420 flat_packed_send_udata.resize(0);
16434 if (my_rank == root_processor)
16449 unsigned rcounter = 0;
16451 for (
unsigned iproc = 0; iproc < nproc; iproc++)
16454 const unsigned n_local_names_iproc = root_n_names_per_processor[iproc];
16455 for (
unsigned i = 0;
i < n_local_names_iproc;
i++)
16459 for (
unsigned j = 0; j < n_info_per_node_name; j++)
16461 node_name[j] = root_flat_packed_receive_udata[rcounter++];
16465 root_local_node_names.push_back(node_name);
16472 const unsigned n_root_local_node_names = root_local_node_names.size();
16487 std::map<Vector<unsigned>,
bool> done_name;
16491 for (
unsigned i = 0;
i < n_root_local_node_names;
i++)
16497 if (!done_name[node_name])
16500 done_name[node_name] =
true;
16504 bool found_both_names_node =
false;
16509 for (
unsigned j =
i + 1; j < n_root_local_node_names; j++)
16514 if (!done_name[node_name_r])
16518 if (node_name[0] == node_name_r[1] &&
16519 node_name[1] == node_name_r[0] &&
16520 node_name[2] == node_name_r[2] &&
16521 node_name[3] == node_name_r[3])
16524 done_name[node_name_r] =
true;
16527 node_name_counter_part[
i] = j;
16530 node_name_counter_part[j] =
i;
16533 found_both_names_node =
true;
16545 if (!found_both_names_node)
16547 std::ostringstream error_message;
16548 error_message <<
"The counter-part of the current name node was "
16549 <<
"not found,\nthe current node name is:\n"
16550 <<
"iproc:(" << node_name[0] <<
")\n"
16551 <<
"jproc:(" << node_name[1] <<
")\n"
16552 <<
"ishd_bnd:(" << node_name[2] <<
")\n"
16553 <<
"index:(" << node_name[3] <<
")\n";
16555 OOMPH_CURRENT_FUNCTION,
16556 OOMPH_EXCEPTION_LOCATION);
16572 for (
unsigned i = 0;
i < n_root_local_node_names;
i++)
16578 if (!done_name[node_name])
16584 all_node_names.push_back(node_name);
16587 unsigned idx_c = node_name_counter_part[
i];
16592 all_node_names.push_back(node_name_r);
16598 unsigned n_current_names = all_node_names.size();
16601 unsigned icounter = 0;
16604 while (icounter < n_current_names)
16612 if (!done_name[current_node_name])
16615 done_name[current_node_name] =
true;
16620 for (
unsigned j =
i + 1; j < n_root_local_node_names; j++)
16626 if (!done_name[other_node_name])
16629 if ((current_node_name[0] == other_node_name[0]) &&
16630 (current_node_name[4] == other_node_name[4]))
16635 done_name[other_node_name] =
true;
16639 std::find(all_node_names.begin(),
16640 all_node_names.end(),
16642 if (it == all_node_names.end())
16644 all_node_names.push_back(other_node_name);
16646 unsigned k = node_name_counter_part[j];
16649 root_local_node_names[k];
16653 if (!done_name[other_node_name_r])
16655 all_node_names.push_back(other_node_name_r);
16669 n_current_names = all_node_names.size();
16677 root_global_node_names.push_back(all_node_names);
16690 flat_packed_root_send_receive_udata.clear();
16692 const unsigned n_global_nodes = root_global_node_names.size();
16695 flat_packed_root_send_receive_udata.push_back(n_global_nodes);
16698 for (
unsigned i = 0;
i < n_global_nodes;
i++)
16703 const unsigned n_names_global_inode = global_inode_names.size();
16706 flat_packed_root_send_receive_udata.push_back(n_names_global_inode);
16708 for (
unsigned j = 0; j < n_names_global_inode; j++)
16711 for (
unsigned k = 0; k < n_info_per_node_name; k++)
16715 flat_packed_root_send_receive_udata.push_back(
16716 global_inode_names[j][k]);
16737 unsigned root_n_udata_sent_to_all_proc =
16738 flat_packed_root_send_receive_udata.size();
16740 MPI_Bcast(&root_n_udata_sent_to_all_proc,
16745 comm_pt->mpi_comm());
16748 if (my_rank != root_processor)
16750 flat_packed_root_send_receive_udata.resize(root_n_udata_sent_to_all_proc);
16754 MPI_Bcast(&flat_packed_root_send_receive_udata[0],
16758 root_n_udata_sent_to_all_proc,
16763 comm_pt->mpi_comm());
16768 const unsigned n_global_nodes =
16769 flat_packed_root_send_receive_udata[counter++];
16776 global_node_names.resize(n_global_nodes);
16778 unsigned n_read_global_nodes = 0;
16779 while (n_read_global_nodes < n_global_nodes)
16782 const unsigned n_names_global_inode =
16783 flat_packed_root_send_receive_udata[counter++];
16785 const unsigned i = n_read_global_nodes;
16787 global_node_names[
i].resize(n_names_global_inode);
16789 for (
unsigned j = 0; j < n_names_global_inode; j++)
16792 global_node_names[
i][j].resize(n_info_per_node_name);
16795 for (
unsigned k = 0; k < n_info_per_node_name; k++)
16799 global_node_names[
i][j][k] =
16800 flat_packed_root_send_receive_udata[counter++];
16807 node_name[0] = global_node_names[
i][j][0];
16808 node_name[1] = global_node_names[
i][j][1];
16809 node_name[2] = global_node_names[
i][j][2];
16810 node_name[3] = global_node_names[
i][j][3];
16815 node_name_to_global_index[node_name] =
i;
16820 n_read_global_nodes++;
16826 if (counter != root_n_udata_sent_to_all_proc)
16828 std::ostringstream error_stream;
16830 <<
"The info. received from root regarding the global names of "
16831 <<
"the nodes\nwas not completely read.\n"
16832 <<
"The number of data sent/received from root is: ("
16833 << root_n_udata_sent_to_all_proc <<
")\n"
16834 <<
"The number of data read from the received info. is: (" << counter
16837 error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
16855 global_shared_node_pt.resize(n_global_nodes, 0);
16858 for (
unsigned i = 0;
i < n_global_nodes;
i++)
16862 bool is_this_a_local_node_name =
false;
16863 unsigned local_node_number;
16865 const unsigned n_names_global_inode = global_node_names[
i].size();
16867 for (
unsigned j = 0; j < n_names_global_inode; j++)
16870 const unsigned iproc = global_node_names[
i][j][0];
16871 local_node_number = global_node_names[
i][j][4];
16874 if (my_rank == iproc)
16877 is_this_a_local_node_name =
true;
16886 if (is_this_a_local_node_name)
16891 const unsigned n_names_local_node =
16892 local_node_names[local_node_number].size();
16893 unsigned n_names_found_on_global_name_node = 0;
16898 global_shared_node_pt[
i] = local_node_pt[local_node_number];
16904 for (
unsigned j = 0; j < n_names_global_inode; j++)
16907 const unsigned iproc = global_node_names[
i][j][0];
16910 if (iproc != my_rank)
16913 local_node_names[local_node_number].push_back(
16914 global_node_names[
i][j]);
16919 const unsigned jproc = global_node_names[
i][j][1];
16920 const unsigned ishd_bnd = global_node_names[
i][j][2];
16921 const unsigned idx = global_node_names[
i][j][3];
16922 const unsigned n_local_node = global_node_names[
i][j][4];
16924 for (
unsigned k = 0; k < n_names_local_node; k++)
16926 if ((local_node_names[local_node_number][k][0] == iproc) &&
16927 (local_node_names[local_node_number][k][1] == jproc) &&
16928 (local_node_names[local_node_number][k][2] == ishd_bnd) &&
16929 (local_node_names[local_node_number][k][3] == idx) &&
16930 (local_node_names[local_node_number][k][4] == n_local_node))
16934 n_names_found_on_global_name_node++;
16948 if (n_names_local_node != n_names_found_on_global_name_node)
16950 std::ostringstream error_stream;
16951 error_stream <<
"The local node names corresponding to the local "
16952 <<
"node (" << local_node_number <<
") were\n"
16953 <<
"not found on the global node names.\n\n"
16954 <<
"These are the names of the local node\n"
16955 <<
"Name k: iproc, jproc, ishd_bnd, idx. #node\n";
16956 for (
unsigned k = 0; k < n_names_local_node; k++)
16958 error_stream <<
"Name(" << k
16959 <<
"): " << local_node_names[local_node_number][k][0]
16960 <<
", " << local_node_names[local_node_number][k][1]
16961 <<
", " << local_node_names[local_node_number][k][2]
16962 <<
", " << local_node_names[local_node_number][k][3]
16963 <<
", " << local_node_names[local_node_number][k][4]
16967 error_stream <<
"\n\nThese are the names of the global node\n"
16968 <<
"Name k: iproc, jproc, ishd_bnd, idx. #node\n";
16969 for (
unsigned k = 0; k < n_names_global_inode; k++)
16971 error_stream <<
"Name(" << k <<
"): " << global_node_names[
i][k][0]
16972 <<
", " << global_node_names[
i][k][1] <<
", "
16973 << global_node_names[
i][k][2] <<
", "
16974 << global_node_names[
i][k][3] <<
", "
16975 << global_node_names[
i][k][4] <<
"\n";
16979 OOMPH_CURRENT_FUNCTION,
16980 OOMPH_EXCEPTION_LOCATION);
17006 const unsigned initial_shd_bnd_id = this->initial_shared_boundary_id();
17009 for (
unsigned i = 0;
i < n_local_nodes;
i++)
17012 const unsigned n_names = local_node_names[
i].size();
17016 Node* node_pt = local_node_pt[
i];
17019 for (
unsigned j = 0; j < n_names; j++)
17022 const unsigned iproc = local_node_names[
i][j][0];
17023 const unsigned jproc = local_node_names[
i][j][1];
17024 const unsigned ishd_bnd =
17025 local_node_names[
i][j][2] - initial_shd_bnd_id;
17026 const unsigned index = local_node_names[
i][j][3];
17033 other_proc_shd_bnd_node_pt[iproc][jproc][ishd_bnd][index] = node_pt;
17037 other_proc_shd_bnd_node_pt[jproc][iproc][ishd_bnd][index] = node_pt;
17055 template<
class ELEMENT>
17062 const unsigned nproc = this->communicator_pt()->nproc();
17063 const unsigned my_rank = this->communicator_pt()->my_rank();
17066 const unsigned n_nodes_on_shd_bnds = global_node_names.size();
17077 std::map<Node*, unsigned> node_pt_to_global_shd_bnd_index;
17081 for (
unsigned i = 0;
i < n_nodes_on_shd_bnds;
i++)
17085 const unsigned n_names = global_node_names[
i].size();
17087 for (
unsigned j = 0; j < n_names; j++)
17091 node_name[0] = global_node_names[
i][j][0];
17092 node_name[1] = global_node_names[
i][j][1];
17093 node_name[2] = global_node_names[
i][j][2];
17094 node_name[3] = global_node_names[
i][j][3];
17097 if (node_name[0] == my_rank)
17100 const unsigned jproc = node_name[1];
17103 std::map<Vector<unsigned>,
unsigned>::iterator it =
17104 node_name_to_global_index.find(node_name);
17105 if (it != node_name_to_global_index.end())
17109 if (
i != (*it).second)
17111 std::ostringstream error_message;
17113 <<
"The global node number " << (*it).second
17114 <<
") obtained from the current node\n"
17115 <<
"name is not the same as the current node number (" <<
i
17118 <<
"iproc:" << node_name[0] <<
"\n"
17119 <<
"jproc:" << node_name[1] <<
"\n"
17120 <<
"shd_bnd_id:" << node_name[2] <<
"\n"
17121 <<
"index:" << node_name[3] <<
"\n\n";
17123 OOMPH_CURRENT_FUNCTION,
17124 OOMPH_EXCEPTION_LOCATION);
17129 std::ostringstream error_message;
17131 <<
"The node name is not registerd as living in this processor.\n"
17133 <<
"iproc:" << node_name[0] <<
"\n"
17134 <<
"jproc:" << node_name[1] <<
"\n"
17135 <<
"shd_bnd_id:" << node_name[2] <<
"\n"
17136 <<
"index:" << node_name[3] <<
"\n\n";
17138 OOMPH_CURRENT_FUNCTION,
17139 OOMPH_EXCEPTION_LOCATION);
17145 Node* node_pt = global_shared_node_pt[
i];
17150 std::ostringstream error_message;
17151 error_message <<
"There is not global shared node within this\n"
17152 <<
"global node number (" <<
i
17153 <<
"). The global shared\n"
17154 <<
"node pointer is null\n\n";
17156 OOMPH_CURRENT_FUNCTION,
17157 OOMPH_EXCEPTION_LOCATION);
17163 node_on_shd_bnd_pt[jproc].insert(node_pt);
17166 node_pt_to_global_shd_bnd_index[node_pt] =
i;
17169 else if (node_name[1] == my_rank)
17172 const unsigned jproc = node_name[0];
17175 std::map<Vector<unsigned>,
unsigned>::iterator it =
17176 node_name_to_global_index.find(node_name);
17177 if (it != node_name_to_global_index.end())
17181 if (
i != (*it).second)
17183 std::ostringstream error_message;
17185 <<
"The global node number " << (*it).second
17186 <<
") obtained from the current node\n"
17187 <<
"name is not the same as the current node number (" <<
i
17190 <<
"iproc:" << node_name[0] <<
"\n"
17191 <<
"jproc:" << node_name[1] <<
"\n"
17192 <<
"shd_bnd_id:" << node_name[2] <<
"\n"
17193 <<
"index:" << node_name[3] <<
"\n\n";
17195 OOMPH_CURRENT_FUNCTION,
17196 OOMPH_EXCEPTION_LOCATION);
17201 std::ostringstream error_message;
17203 <<
"The node name is not registerd as living in this processor.\n"
17205 <<
"iproc:" << node_name[0] <<
"\n"
17206 <<
"jproc:" << node_name[1] <<
"\n"
17207 <<
"shd_bnd_id:" << node_name[2] <<
"\n"
17208 <<
"index:" << node_name[3] <<
"\n\n";
17210 OOMPH_CURRENT_FUNCTION,
17211 OOMPH_EXCEPTION_LOCATION);
17217 Node* node_pt = global_shared_node_pt[
i];
17222 std::ostringstream error_message;
17223 error_message <<
"There is not global shared node within this\n"
17224 <<
"global node number (" <<
i
17225 <<
"). The global shared\n"
17226 <<
"node pointer is null\n\n";
17228 OOMPH_CURRENT_FUNCTION,
17229 OOMPH_EXCEPTION_LOCATION);
17235 node_on_shd_bnd_pt[jproc].insert(node_pt);
17238 node_pt_to_global_shd_bnd_index[node_pt] =
i;
17264 for (
unsigned iproc = 0; iproc < nproc; iproc++)
17267 std::set<Node*> nodes_shared_pt = node_on_shd_bnd_pt[iproc];
17270 for (std::set<Node*>::iterator it = nodes_shared_pt.begin();
17271 it != nodes_shared_pt.end();
17275 Node* node_pt = (*it);
17282 const unsigned n_bnd = this->initial_shared_boundary_id();
17285 for (
unsigned bb = 0; bb < n_bnd; bb++)
17288 if (node_pt->is_on_boundary(bb))
17291 on_original_boundaries.push_back(bb);
17294 node_pt->get_coordinates_on_boundary(bb, zeta);
17296 zeta_coordinate.push_back(zeta[0]);
17302 if (on_original_boundaries.size() > 0)
17305 std::map<Node*, unsigned>::iterator it_index =
17306 node_pt_to_global_shd_bnd_index.find(node_pt);
17308 if (it_index == node_pt_to_global_shd_bnd_index.end())
17310 std::ostringstream error_message;
17312 <<
"We could not find the global shared node index associated\n"
17313 <<
"with the node pointer with vertices coordinates:\n"
17314 <<
"(" << node_pt->x(0) <<
", " << node_pt->x(1) <<
")\n\n";
17316 OOMPH_CURRENT_FUNCTION,
17317 OOMPH_EXCEPTION_LOCATION);
17321 const unsigned global_shared_node_number = (*it_index).second;
17323 global_node_on_shared_bound[iproc].push_back(
17324 global_shared_node_number);
17326 global_node_original_boundaries[iproc].push_back(
17327 on_original_boundaries);
17329 global_node_zeta_coordinate[iproc].push_back(zeta_coordinate);
17353 MPI_Request request;
17356 for (
unsigned iproc = 0; iproc < nproc; iproc++)
17359 const unsigned n_shd_nodes_my_rank_iproc =
17360 node_on_shd_bnd_pt[iproc].size();
17364 if (n_shd_nodes_my_rank_iproc > 0 && iproc != my_rank)
17370 flat_package_unsigned_send.push_back(n_shd_nodes_my_rank_iproc);
17373 const unsigned n_global_shared_node_on_original_boundary =
17374 global_node_on_shared_bound[iproc].size();
17378 flat_package_unsigned_send.push_back(
17379 n_global_shared_node_on_original_boundary);
17386 for (
unsigned i = 0;
i < n_global_shared_node_on_original_boundary;
i++)
17389 const unsigned global_shared_node_index =
17390 global_node_on_shared_bound[iproc][
i];
17394 flat_package_unsigned_send.push_back(global_shared_node_index);
17398 global_node_original_boundaries[iproc][
i];
17402 global_node_zeta_coordinate[iproc][
i];
17406 const unsigned n_original_boundaries = on_original_boundaries.size();
17410 flat_package_unsigned_send.push_back(n_original_boundaries);
17414 for (
unsigned j = 0; j < n_original_boundaries; j++)
17418 flat_package_unsigned_send.push_back(on_original_boundaries[j]);
17420 flat_package_double_send.push_back(zeta_coordinate[j]);
17428 const unsigned n_udata_send = flat_package_unsigned_send.size();
17429 int n_udata_send_int = n_udata_send;
17432 MPI_Isend(&n_udata_send_int,
17437 comm_pt->mpi_comm(),
17440 int n_udata_received_int = 0;
17441 MPI_Recv(&n_udata_received_int,
17446 comm_pt->mpi_comm(),
17448 MPI_Wait(&request, MPI_STATUS_IGNORE);
17450 if (n_udata_send != 0)
17452 MPI_Isend(&flat_package_unsigned_send[0],
17457 comm_pt->mpi_comm(),
17461 const unsigned n_udata_received =
17462 static_cast<unsigned>(n_udata_received_int);
17467 if (n_udata_received != 0)
17469 MPI_Recv(&flat_package_unsigned_receive[0],
17474 comm_pt->mpi_comm(),
17478 if (n_udata_send != 0)
17480 MPI_Wait(&request, MPI_STATUS_IGNORE);
17486 const unsigned n_ddata_send = flat_package_double_send.size();
17487 int n_ddata_send_int = n_ddata_send;
17490 MPI_Isend(&n_ddata_send_int,
17495 comm_pt->mpi_comm(),
17498 int n_ddata_received_int = 0;
17499 MPI_Recv(&n_ddata_received_int,
17504 comm_pt->mpi_comm(),
17506 MPI_Wait(&request, MPI_STATUS_IGNORE);
17508 if (n_ddata_send != 0)
17510 MPI_Isend(&flat_package_double_send[0],
17515 comm_pt->mpi_comm(),
17519 const unsigned n_ddata_received =
17520 static_cast<unsigned>(n_ddata_received_int);
17525 if (n_ddata_received != 0)
17527 MPI_Recv(&flat_package_double_receive[0],
17532 comm_pt->mpi_comm(),
17536 if (n_ddata_send != 0)
17538 MPI_Wait(&request, MPI_STATUS_IGNORE);
17546 unsigned n_shared_nodes_received = flat_package_unsigned_receive[0];
17550 n_shared_nodes_received++;
17551 n_shared_nodes_received--;
17554 if (n_shd_nodes_my_rank_iproc != n_shared_nodes_received)
17556 std::ostringstream error_message;
17558 <<
"The number of shared nodes between the pair of processors is\n"
17559 <<
"not the same\n"
17560 <<
"N.shared nodes proc (" << my_rank <<
") with proc (" << iproc
17561 <<
"): (" << n_shd_nodes_my_rank_iproc <<
"\n"
17562 <<
"N.shared nodes proc (" << iproc <<
") with proc (" << my_rank
17563 <<
"): (" << n_shared_nodes_received <<
"\n\n"
17564 <<
"You should have got the same error in proc: (" << iproc
17567 OOMPH_CURRENT_FUNCTION,
17568 OOMPH_EXCEPTION_LOCATION);
17581 unsigned current_index_data = 2;
17582 unsigned current_index_ddata = 0;
17583 while (current_index_data < n_udata_received)
17586 const unsigned global_shared_node_index =
17587 flat_package_unsigned_receive[current_index_data++];
17594 const unsigned n_original_boundaries =
17595 flat_package_unsigned_receive[current_index_data++];
17598 node_pt = global_shared_node_pt[global_shared_node_index];
17602 std::ostringstream error_message;
17604 <<
"The global shared node (" << global_shared_node_index <<
") "
17605 <<
"could not be found in this processor!!!\n"
17606 <<
"However, it was found in processor (" << iproc <<
"). The "
17607 <<
"data may be no synchronised,\ntherefore "
17608 <<
"we may be looking for a global shared node number that "
17609 <<
"do not\ncorrespond with the one that was sent by "
17610 <<
"processor (" << iproc <<
")\n\n";
17612 OOMPH_CURRENT_FUNCTION,
17613 OOMPH_EXCEPTION_LOCATION);
17619 for (
unsigned i = 0;
i < n_original_boundaries;
i++)
17623 const unsigned original_bound_id =
17624 flat_package_unsigned_receive[current_index_data++];
17627 this->add_boundary_node(original_bound_id, node_pt);
17631 zeta[0] = flat_package_double_receive[current_index_ddata++];
17632 node_pt->set_coordinates_on_boundary(original_bound_id, zeta);
17654 template<
class ELEMENT>
17657 other_proc_shd_bnd_node_pt,
17664 const unsigned nproc = this->communicator_pt()->nproc();
17665 const unsigned my_rank = this->communicator_pt()->my_rank();
17673 std::map<Node*, bool> is_global_shared_node;
17674 std::map<Node*, unsigned> global_shared_node_index;
17677 const unsigned n_global_shared_nodes = global_shared_node_pt.size();
17679 for (
unsigned i = 0;
i < n_global_shared_nodes;
i++)
17682 Node* node_pt = global_shared_node_pt[
i];
17684 is_global_shared_node[node_pt] =
true;
17686 global_shared_node_index[node_pt] =
i;
17709 for (
unsigned iproc = 0; iproc < nproc; iproc++)
17711 if (iproc != my_rank)
17715 this->root_haloed_element_pt(iproc);
17718 const unsigned n_haloed_ele = this->nroot_haloed_element(iproc);
17721 for (
unsigned ihd = 0; ihd < n_haloed_ele; ihd++)
17728 const unsigned n_nodes = ele_pt->
nnode();
17730 for (
unsigned n = 0; n < n_nodes; n++)
17733 Node* node_pt = ele_pt->
node_pt(n);
17735 if (is_global_shared_node[node_pt])
17738 const unsigned global_index = global_shared_node_index[node_pt];
17741 global_node_names[global_index];
17744 const unsigned n_names = iglobal_names.size();
17748 for (
unsigned j = 0; j < n_names; j++)
17752 const unsigned proc1 = iglobal_names[j][0];
17753 const unsigned proc2 = iglobal_names[j][1];
17756 additional_elements_pt[proc1].insert(gele_pt);
17757 additional_elements_pt[proc2].insert(gele_pt);
17780 for (
unsigned iproc = 0; iproc < nproc; iproc++)
17782 if (iproc != my_rank)
17786 std::set<GeneralisedElement*> iproc_ele_pt =
17787 additional_elements_pt[iproc];
17790 for (std::set<GeneralisedElement*>::iterator it = iproc_ele_pt.begin();
17791 it != iproc_ele_pt.end();
17799 this->root_haloed_element_pt(iproc);
17802 const unsigned n_haloed_ele = this->nroot_haloed_element(iproc);
17806 bool send_ele_to_iproc_processor =
true;
17811 for (
unsigned ihd = 0; ihd < n_haloed_ele; ihd++)
17815 if (gele_pt == ghd_ele_pt)
17818 send_ele_to_iproc_processor =
false;
17827 if (send_ele_to_iproc_processor)
17833 send_haloed_ele_pt[iproc].push_back(ele_pt);
17855 for (
unsigned iproc = 0; iproc < nproc; iproc++)
17858 if (iproc != my_rank)
17861 const unsigned n_additional_haloed_ele =
17862 send_haloed_ele_pt[iproc].size();
17867#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
17875#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
17876 std::stringstream junk;
17877 junk <<
"Number of haloed elements " << nhaloed_ele;
17882 for (
unsigned e = 0;
e < n_additional_haloed_ele;
e++)
17886 const unsigned nroot_haloed_ele = this->nroot_haloed_element(iproc);
17894 const unsigned haloed_ele_index =
17895 this->try_to_add_root_haloed_element_pt(iproc, gen_ele_pt);
17899 if (nroot_haloed_ele == haloed_ele_index)
17902#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
17904 "Haloed element needs to be constructed");
17908 get_required_elemental_information_helper(iproc, ele_pt);
17911 const unsigned nnodes = ele_pt->
nnode();
17912 for (
unsigned j = 0; j < nnodes; j++)
17914 Node* node_pt = ele_pt->
node_pt(j);
17918 add_haloed_node_helper(iproc, node_pt);
17926#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
17928 "Haloed element already exists");
17931#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
17933 "Index of existing haloed element");
17943 int send_proc =
static_cast<int>(iproc);
17945 int recv_proc =
static_cast<int>(iproc);
17946 send_and_receive_elements_nodes_info(send_proc, recv_proc);
17953 const unsigned n_additional_halo_ele =
17956#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
17958 <<
" Number of elements need to be constructed "
17964 for (
unsigned e = 0;
e < n_additional_halo_ele;
e++)
17968 create_halo_element(iproc,
17969 iproc_currently_created_nodes_pt[iproc],
17970 other_proc_shd_bnd_node_pt,
17972 node_name_to_global_index,
17973 global_shared_node_pt);
17991 template<
class ELEMENT>
17993 ELEMENT>::get_required_elemental_information_helper(
unsigned& iproc,
17997 const unsigned nbound = this->initial_shared_boundary_id();
18005 unsigned counter_face_indexes = 0;
18007 for (
unsigned b = 0; b < nbound; b++)
18010 const unsigned nboundary_ele = nboundary_element(b);
18011 for (
unsigned e = 0;
e < nboundary_ele;
e++)
18013 if (ele_pt == this->boundary_element_pt(b,
e))
18016 associated_boundaries.push_back(b);
18018 face_index_on_boundary.push_back(face_index_at_boundary(b,
e));
18019 counter_face_indexes++;
18021 if (counter_face_indexes > 2)
18023 std::stringstream error_message;
18025 <<
"A triangular element can not have more than two of its faces "
18026 <<
"on a boundary!!!\n\n";
18028 OOMPH_CURRENT_FUNCTION,
18029 OOMPH_EXCEPTION_LOCATION);
18033 if (counter_face_indexes == 2)
18047 const unsigned nassociated_boundaries = associated_boundaries.size();
18048 if (nassociated_boundaries > 0)
18051#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18053 "The element is a boundary element");
18056#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18057 std::stringstream junk;
18058 junk <<
"The elements is associated to " << nassociated_boundaries
18067 for (
unsigned i = 0;
i < nassociated_boundaries;
i++)
18069 unsigned b = associated_boundaries[
i];
18071#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18072 std::stringstream junk;
18073 junk <<
"Element associated to boundary " << b <<
" of "
18074 << nassociated_boundaries <<
" total associated boundaries";
18077 unsigned f = face_index_on_boundary[
i];
18079#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18080 std::stringstream junk2;
18081 junk2 <<
"Face index " <<
f <<
" for associated boundary " << b;
18096 const unsigned n_regions = this->nregion();
18101 unsigned counter_face_indexes_in_regions = 0;
18103 for (
unsigned b = 0; b < nbound; b++)
18106 for (
unsigned i_reg = 0; i_reg < n_regions; i_reg++)
18109 const unsigned region_id =
18110 static_cast<unsigned>(this->Region_attribute[i_reg]);
18115 const unsigned nele_in_region =
18116 this->nboundary_element_in_region(b, region_id);
18117 for (
unsigned ee = 0; ee < nele_in_region; ee++)
18122 this->boundary_element_in_region_pt(b, region_id, ee))
18129 bound_and_region[0] = b;
18131 bound_and_region[1] = region_id;
18134 associated_boundaries_and_regions.push_back(bound_and_region);
18136 face_index_on_boundary_and_region.push_back(
18137 this->face_index_at_boundary_in_region(b, region_id, ee));
18141 counter_face_indexes_in_regions++;
18144 if (counter_face_indexes_in_regions > 2)
18146 std::stringstream error_message;
18147 error_message <<
"A triangular element can not have more "
18148 "than two of its\n"
18149 <<
"faces on a boundary!!!\n\n";
18151 OOMPH_CURRENT_FUNCTION,
18152 OOMPH_EXCEPTION_LOCATION);
18167 const unsigned nassociated_boundaries_and_regions =
18168 associated_boundaries_and_regions.size();
18169 if (nassociated_boundaries_and_regions > 0)
18172#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18174 "The element is associated to boundaries and regions");
18178#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18179 std::stringstream junk;
18180 junk <<
"The element is associated to "
18181 << nassociated_boundaries_and_regions <<
" boundaries-regions";
18189 for (
unsigned i = 0;
i < nassociated_boundaries_and_regions;
i++)
18191 const unsigned b = associated_boundaries_and_regions[
i][0];
18193#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18194 std::stringstream junk;
18195 junk <<
"Element associated to boundary " << b <<
" of "
18196 << nassociated_boundaries_and_regions
18197 <<
" total associated boundaries-regions";
18201 const unsigned r = associated_boundaries_and_regions[
i][1];
18203#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18204 std::stringstream junk2;
18205 junk2 <<
"Element associated to region " << r <<
" of "
18206 << nassociated_boundaries_and_regions
18207 <<
" total associated boundaries-regions";
18211 const unsigned f = face_index_on_boundary_and_region[
i];
18213#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18214 std::stringstream junk3;
18215 junk3 <<
"Face index " <<
f <<
" for associated boundary-region ("
18216 << b <<
"-" << r <<
")";
18224#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18226 "The element is NOT associated to boundaries and regions");
18233#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18235 "The element is not associated to any original boundary");
18249 this->shared_boundaries_in_this_processor(my_rank_shared_boundaries_ids);
18252 const unsigned nmy_rank_shd_bnd = my_rank_shared_boundaries_ids.size();
18254 for (
unsigned i = 0;
i < nmy_rank_shd_bnd;
i++)
18257 const unsigned sb = my_rank_shared_boundaries_ids[
i];
18260 const unsigned nboundary_ele = this->nshared_boundary_element(sb);
18261 for (
unsigned e = 0;
e < nboundary_ele;
e++)
18263 if (ele_pt == this->shared_boundary_element_pt(sb,
e))
18266 associated_shared_boundaries.push_back(sb);
18268 face_index_on_shared_boundary.push_back(
18269 this->face_index_at_shared_boundary(sb,
e));
18276 const unsigned nassociated_shared_boundaries =
18277 associated_shared_boundaries.size();
18278 if (nassociated_shared_boundaries > 0)
18281#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18283 "The element is a shared boundary element");
18286#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18287 std::stringstream junk;
18288 junk <<
"The elements is associated to " << nassociated_shared_boundaries
18289 <<
"shared boundaries";
18294 for (
unsigned i = 0;
i < nassociated_shared_boundaries;
i++)
18296 const unsigned b = associated_shared_boundaries[
i];
18298#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18299 std::stringstream junk;
18300 junk <<
"Element associated to shared boundary " << b <<
" of "
18301 << nassociated_shared_boundaries <<
" total associated boundaries";
18305 const unsigned f = face_index_on_shared_boundary[
i];
18307#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18308 std::stringstream junk2;
18309 junk2 <<
"Face index " <<
f <<
" for associated shared boundary " << b;
18317#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18319 "The element is not associated to any shared boundary");
18329 template<
class ELEMENT>
18331 unsigned& iproc, Node* nod_pt)
18333 unsigned my_rank = this->communicator_pt()->my_rank();
18334 const unsigned nproc = this->communicator_pt()->nproc();
18339 unsigned n_val = nod_pt->nvalue();
18341#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18345 unsigned n_dim = nod_pt->ndim();
18348 unsigned n_prev = 1;
18349 if (this->Time_stepper_pt != 0)
18352 n_prev = this->Time_stepper_pt->ntstorage();
18361 const unsigned n_bnd = this->initial_shared_boundary_id();
18362 for (
unsigned bb = 0; bb < n_bnd; bb++)
18365 if (nod_pt->is_on_boundary(bb))
18367 original_boundaries.push_back(bb);
18371 const unsigned n_original_boundaries = original_boundaries.size();
18373 if (n_original_boundaries > 0)
18377#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18379 "Node is on the original boundaries");
18383#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18384 std::stringstream junk;
18385 junk <<
"Node is on " << n_original_boundaries <<
" original boundaries";
18390 for (
unsigned i = 0;
i < n_original_boundaries;
i++)
18393#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18394 std::stringstream junk;
18395 junk <<
"Node is on boundary " << original_boundaries[
i] <<
" of "
18401 nod_pt->get_coordinates_on_boundary(original_boundaries[
i], zeta);
18409#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18411 "Node is on any original boundary");
18417 bool node_on_shared_boundary =
false;
18420 const unsigned n_shd_bnd = this->nshared_boundaries(my_rank, iproc);
18421 for (
unsigned bb = 0; bb < n_shd_bnd; bb++)
18424 unsigned i_bnd = this->shared_boundaries_ids(my_rank, iproc, bb);
18426 if (this->is_node_on_shared_boundary(i_bnd, nod_pt))
18428 node_on_shared_boundary =
true;
18436 if (node_on_shared_boundary)
18439#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18446 for (
unsigned bb = 0; bb < n_shd_bnd; bb++)
18449 const unsigned i_bnd = this->shared_boundaries_ids(my_rank, iproc, bb);
18451 if (this->is_node_on_shared_boundary(i_bnd, nod_pt))
18453 shd_boundaries.push_back(i_bnd);
18458 const unsigned n_shd_bnd_is_on = shd_boundaries.size();
18461#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18462 std::stringstream junk;
18463 junk <<
"Node is on " << n_shd_bnd_is_on <<
" shared boundaries";
18468 for (
unsigned i = 0;
i < n_shd_bnd_is_on;
i++)
18471#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18472 std::stringstream junk;
18473 junk <<
"Node is on boundary " << shd_boundaries[
i] <<
" of " << nb;
18480 unsigned shared_boundary_id = shd_boundaries[0];
18482 const unsigned n_nodes_on_shared_boundary =
18483 nsorted_shared_boundary_node(shared_boundary_id);
18485 unsigned index_node_on_shared_boundary;
18488 bool found_index_node_on_shared_boundary =
false;
18491 for (
unsigned i = 0;
i < n_nodes_on_shared_boundary;
i++)
18494 Node* shared_node_pt =
18495 sorted_shared_boundary_node_pt(shared_boundary_id,
i);
18497 if (shared_node_pt == nod_pt)
18500 index_node_on_shared_boundary =
i;
18503 found_index_node_on_shared_boundary =
true;
18511 if (!found_index_node_on_shared_boundary)
18513 std::ostringstream error_message;
18514 error_message <<
"The index of the node on boundary ("
18515 << shared_boundary_id <<
") was not found.\n"
18516 <<
"The node coordinates are (" << nod_pt->x(0) <<
","
18517 << nod_pt->x(1) <<
").\n";
18519 error_message.str(),
18520 "RefineableTriangleMesh::get_required_nodal_information_helper()",
18521 OOMPH_EXCEPTION_LOCATION);
18526#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18527 std::stringstream junk2;
18528 junk2 <<
"Node index on boundary " << boundaries[0] <<
" is "
18529 << index_node_on_shared_boundary;
18538#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18540 "Node is not on a shared boundary");
18555 bool node_on_shared_boundary_with_other_processors =
false;
18557 unsigned nshared_boundaries_with_other_processors_have_node = 0;
18561 for (
unsigned jproc = 0; jproc < nproc; jproc++)
18565 if (jproc != iproc)
18568 const unsigned n_jshd_bnd = this->nshared_boundaries(my_rank, jproc);
18570 for (
unsigned bb = 0; bb < n_jshd_bnd; bb++)
18573 const unsigned j_shd_bnd =
18574 this->shared_boundaries_ids(my_rank, jproc, bb);
18576 if (this->is_node_on_shared_boundary(j_shd_bnd, nod_pt))
18584 node_on_shared_boundary_with_other_processors =
true;
18587 nshared_boundaries_with_other_processors_have_node++;
18598 if (node_on_shared_boundary_with_other_processors)
18601#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18603 "Node is on shared boundary no related with the received processor: 4");
18610 nshared_boundaries_with_other_processors_have_node);
18611#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18612 std::stringstream junk;
18613 junk <<
"Number of other shared boundaries that the node is on: "
18614 << nshared_boundaries_with_other_processors_have_node;
18619 unsigned counter_shd_bnd_with_other_procs_have_node = 0;
18629 for (
unsigned jproc = 0; jproc < nproc; jproc++)
18633 if (jproc != iproc)
18637 const unsigned n_jshd_bnd = this->nshared_boundaries(my_rank, jproc);
18638 for (
unsigned bb = 0; bb < n_jshd_bnd; bb++)
18641 const unsigned j_shd_bnd =
18642 this->shared_boundaries_ids(my_rank, jproc, bb);
18644 if (this->is_node_on_shared_boundary(j_shd_bnd, nod_pt))
18647 other_processor_1.push_back(my_rank);
18649 other_processor_2.push_back(jproc);
18651 shd_bnd_ids.push_back(j_shd_bnd);
18654 counter_shd_bnd_with_other_procs_have_node++;
18665 const unsigned n_other_processors = other_processor_1.size();
18667 for (
unsigned i = 0;
i < n_other_processors;
i++)
18670 unsigned shd_bnd_id = shd_bnd_ids[
i];
18672 const unsigned n_nodes_on_shd_bnd =
18673 nsorted_shared_boundary_node(shd_bnd_id);
18676 bool found_index_node_on_shared_boundary =
false;
18678 for (
unsigned i = 0;
i < n_nodes_on_shd_bnd;
i++)
18681 Node* shared_node_pt = sorted_shared_boundary_node_pt(shd_bnd_id,
i);
18683 if (shared_node_pt == nod_pt)
18689 indexes.push_back(
i);
18692 found_index_node_on_shared_boundary =
true;
18700 if (!found_index_node_on_shared_boundary)
18702 std::ostringstream error_message;
18703 error_message <<
"The index of the node on boundary (" << shd_bnd_id
18704 <<
"), shared by other processors\nwas not found.\n"
18705 <<
"The node coordinates are (" << nod_pt->x(0) <<
","
18706 << nod_pt->x(1) <<
").\n";
18708 error_message.str(),
18709 "RefineableTriangleMesh::get_required_nodal_information_helper()",
18710 OOMPH_EXCEPTION_LOCATION);
18719 if (counter_shd_bnd_with_other_procs_have_node !=
18720 nshared_boundaries_with_other_processors_have_node)
18722 std::ostringstream error_message;
18723 error_message <<
"The number of shared boundaries where the node is on "
18724 <<
"is different:\n"
18725 <<
"nshared_boundaries_with_other_processors_have_node: ("
18726 << nshared_boundaries_with_other_processors_have_node
18728 <<
"counter_shd_bnd_with_other_procs_have_node: ("
18729 << counter_shd_bnd_with_other_procs_have_node <<
")\n";
18731 error_message.str(),
18732 "RefineableTriangleMesh::get_required_nodal_information_helper()",
18733 OOMPH_EXCEPTION_LOCATION);
18739 for (
unsigned i = 0;
i < n_other_processors;
i++)
18742#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18743 std::stringstream junk1;
18744 junk1 <<
"Processor where the other shared boundary "
18745 <<
"has the node: " << other_processor_1[
i];
18750#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18751 std::stringstream junk2;
18752 junk2 <<
"Processor where the other shared boundary "
18753 <<
"has the node: " << other_processor_2[
i];
18758#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18759 std::stringstream junk3;
18760 junk3 <<
"Other shared boundary id where the node is on"
18766#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18767 std::stringstream junk4;
18768 junk4 <<
"Node index on other shared boundary " << boundaries[
i]
18769 <<
" is " << indexes[
i];
18779#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18781 "Node is on any shared boundary with other processors");
18789 if (!node_on_shared_boundary)
18797 if (alg_nod_pt != 0)
18805#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18810 unsigned n_ref_val = alg_nod_pt->
nref_value();
18812#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18815 for (
unsigned i_ref_val = 0; i_ref_val < n_ref_val; i_ref_val++)
18823#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18826 for (
unsigned i_geom = 0; i_geom < n_geom_obj; i_geom++)
18834 unsigned found_geom_object = 0;
18835 for (
unsigned i_list = 0; i_list < n_geom_list; i_list++)
18839 found_geom_object = i_list;
18843#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18851 if (solid_nod_pt != 0)
18854 for (
unsigned i_val = 0; i_val < n_solid_val; i_val++)
18856 for (
unsigned t = 0;
t < n_prev;
t++)
18865 const unsigned nvalues_solid_node = values_solid_node.size();
18867#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18868 std::stringstream junk;
18869 junk <<
"Number of values solid node: " << nvalues_solid_node;
18872 for (
unsigned i = 0;
i < nvalues_solid_node;
i++)
18879 for (
unsigned i_val = 0; i_val < n_val; i_val++)
18881 for (
unsigned t = 0;
t < n_prev;
t++)
18888 for (
unsigned idim = 0; idim < n_dim; idim++)
18890 for (
unsigned t = 0;
t < n_prev;
t++)
18902 template<
class ELEMENT>
18907 const unsigned n_haloed_nod = this->nhaloed_node(iproc);
18908 const unsigned haloed_node_index =
18909 this->try_to_add_haloed_node_pt(iproc, nod_pt);
18912 if (haloed_node_index == n_haloed_nod)
18916#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18917 std::stringstream junk;
18918 junk <<
"Node needs to be constructed [size="
18932#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18933 std::stringstream junk;
18935 <<
"]; last entry: "
18944#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18954 template<
class ELEMENT>
18956 int& send_proc,
int& recv_proc)
18963 MPI_Request request;
18972 MPI_Isend(&send_count_double_values,
18977 comm_pt->mpi_comm(),
18980 int receive_count_double_values = 0;
18981 MPI_Recv(&receive_count_double_values,
18986 comm_pt->mpi_comm(),
18988 MPI_Wait(&request, MPI_STATUS_IGNORE);
18990 if (send_count_double_values != 0)
18993 send_count_double_values,
18997 comm_pt->mpi_comm(),
19000 if (receive_count_double_values != 0)
19002 received_double_values.resize(receive_count_double_values);
19003 MPI_Recv(&received_double_values[0],
19004 receive_count_double_values,
19008 comm_pt->mpi_comm(),
19011 if (send_count_double_values != 0)
19013 MPI_Wait(&request, MPI_STATUS_IGNORE);
19019#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19022 if (send_count_unsigned_string != send_count_unsigned_values)
19024 std::ostringstream error_message;
19025 error_message <<
"The number of unsigned values to send to processor ("
19027 <<
") is different from the\nnumber of annotated strings "
19028 <<
"for the communication\n\n";
19030 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
19034 MPI_Isend(&send_count_unsigned_values,
19039 comm_pt->mpi_comm(),
19042 int receive_count_unsigned_values = 0;
19043 MPI_Recv(&receive_count_unsigned_values,
19048 comm_pt->mpi_comm(),
19051 MPI_Wait(&request, MPI_STATUS_IGNORE);
19053 if (send_count_unsigned_values != 0)
19056 send_count_unsigned_values,
19060 comm_pt->mpi_comm(),
19062#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19063 for (
unsigned i = 0;
i < send_count_unsigned_values;
i++)
19065 oomph_info <<
"Sent:" <<
i <<
" to orig_proc:" << send_proc <<
" "
19071 if (receive_count_unsigned_values != 0)
19073 received_unsigned_values.resize(receive_count_unsigned_values);
19074 MPI_Recv(&received_unsigned_values[0],
19075 receive_count_unsigned_values,
19079 comm_pt->mpi_comm(),
19083 if (send_count_unsigned_values != 0)
19085 MPI_Wait(&request, MPI_STATUS_IGNORE);
19095 for (
int ii = 0; ii < receive_count_double_values; ii++)
19100 for (
int ii = 0; ii < receive_count_unsigned_values; ii++)
19110 template<
class ELEMENT>
19115 other_proc_shd_bnd_node_pt,
19120#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19122 <<
" Bool: New element needs to be constructed "
19134 this->add_element_pt(new_el_pt);
19137 this->add_root_halo_element_pt(iproc, new_el_pt);
19143 this->add_halo_element_helper(iproc, f_el_pt);
19146 unsigned n_node = f_el_pt->
nnode();
19148 for (
unsigned j = 0; j < n_node; j++)
19150 Node* new_nod_pt = 0;
19153 add_halo_node_helper(new_nod_pt,
19154 new_nodes_on_domain,
19155 other_proc_shd_bnd_node_pt,
19160 node_name_to_global_index,
19161 global_shared_node_pt);
19167#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19169 <<
" Index of existing halo element "
19174 unsigned halo_ele_index =
19179 this->root_halo_element_pt(iproc, halo_ele_index));
19184 throw OomphLibError(
"Halo element is not a FiniteElement\n",
19185 OOMPH_CURRENT_FUNCTION,
19186 OOMPH_EXCEPTION_LOCATION);
19198 template<
class ELEMENT>
19202#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19204 <<
" Bool: Element is associated to an original boundary "
19211#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19213 <<
" How many boundaries are associated with the element "
19217 const unsigned nassociated_boundaries =
19220 for (
unsigned b = 0; b < nassociated_boundaries; b++)
19222#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19224 <<
" Boundary associated to the element "
19228 const unsigned bnd =
19231#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19233 <<
" Face index of the element "
19237 const unsigned face_index =
19242 this->Boundary_element_pt[bnd].push_back(ele_pt);
19243 this->Face_index_at_boundary[bnd].push_back(face_index);
19248#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19250 <<
" Bool: Element is associated to a boundary-region "
19257#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19260 <<
" How many boundaries-regions are associated with the element "
19264 const unsigned nassociated_boundaries_and_regions =
19267 for (
unsigned br = 0; br < nassociated_boundaries_and_regions; br++)
19269#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19271 <<
" Boundary associated to the element "
19275 const unsigned bnd =
19278#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19280 <<
" Region associated to the element "
19284 const unsigned region =
19287#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19289 <<
" Face index of the element in boundary-region "
19293 const unsigned face_index =
19298 this->Boundary_region_element_pt[bnd][region].push_back(ele_pt);
19299 this->Face_index_region_at_boundary[bnd][region].push_back(
19308#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19310 <<
" Bool: Element is associated to a shared boundary "
19316#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19319 <<
" How many shared boundaries are associated with the element "
19323 const unsigned nassociated_shared_boundaries =
19326 for (
unsigned b = 0; b < nassociated_shared_boundaries; b++)
19328#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19330 <<
" Shared boundary associated to the element "
19334 const unsigned bnd =
19337#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19340 <<
" Face index of the element associated to the shared boundary "
19345 const unsigned face_index =
19348 this->add_shared_boundary_element(bnd, ele_pt);
19349 this->add_face_index_at_shared_boundary(bnd, face_index);
19359 template<
class ELEMENT>
19364 other_proc_shd_bnd_node_pt,
19366 unsigned& node_index,
19374#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19376 <<
" Bool: New node needs to be constructed "
19384 construct_new_halo_node_helper(new_nod_pt,
19385 new_nodes_on_domain,
19386 other_proc_shd_bnd_node_pt,
19391 node_name_to_global_index,
19392 global_shared_node_pt);
19396#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19398 <<
" Index of existing halo node "
19404 new_nod_pt = new_nodes_on_domain
19407 new_el_pt->
node_pt(node_index) = new_nod_pt;
19415 template<
class ELEMENT>
19420 other_proc_shd_bnd_node_pt,
19422 unsigned& node_index,
19430#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19432 <<
" Number of values of external halo node "
19439 TimeStepper* time_stepper_pt = this->Time_stepper_pt;
19441 unsigned n_prev = time_stepper_pt->
ntstorage();
19445#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19447 <<
" Is the node on an original boundary "
19453 const unsigned node_on_original_boundaries =
19461 unsigned n_original_boundaries_node_is_on = 0;
19463 if (node_on_original_boundaries == 2)
19466#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19468 <<
" Number of boundaries the node is on: "
19472 n_original_boundaries_node_is_on =
19476 original_boundaries_node_is_on.resize(n_original_boundaries_node_is_on);
19477 zeta_coordinates.resize(n_original_boundaries_node_is_on);
19479 for (
unsigned i = 0;
i < n_original_boundaries_node_is_on;
i++)
19482#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19484 <<
" Node is on boundary "
19488 original_boundaries_node_is_on[
i] =
19490 zeta_coordinates[
i] =
19498 if (node_on_original_boundaries != 0)
19500 std::ostringstream error_message;
19502 <<
"The current node is not on an original boundary, this should\n"
19503 <<
"be indicated by a zero flag. However, the read value for\n"
19504 <<
"that flag is (" << node_on_original_boundaries <<
").\n\n";
19506 error_message.str(),
19507 "RefineableTriangleMesh::construct_new_halo_node_helper()",
19508 OOMPH_EXCEPTION_LOCATION);
19516#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19518 <<
" Is node on shared boundary? "
19522 const unsigned is_node_on_shared_boundary =
19524 if (is_node_on_shared_boundary == 1)
19527#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19529 <<
" Number of boundaries the node is on: "
19533 const unsigned n_shd_bnd_node_is_on =
19536 for (
unsigned i = 0;
i < n_shd_bnd_node_is_on;
i++)
19539#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19541 <<
" Node is on boundary "
19545 shd_bnds_node_is_on[
i] =
19550#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19552 <<
" Index of node on boundary "
19557 unsigned node_index_on_shared_boundary =
19561 new_nod_pt = this->sorted_shared_boundary_node_pt(
19562 shd_bnds_node_is_on[0], node_index_on_shared_boundary);
19568 if (is_node_on_shared_boundary != 0)
19570 std::ostringstream error_message;
19572 <<
"The current node is not on a shared boundary, this should\n"
19573 <<
"be indicated by a zero flag. However, the read value for\n"
19574 <<
"that flag is (" << is_node_on_shared_boundary <<
").\n\n";
19576 error_message.str(),
19577 "RefineableTriangleMesh::construct_new_halo_node_helper()",
19578 OOMPH_EXCEPTION_LOCATION);
19585#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19587 <<
" Is the node on shared boundaries with other processors "
19594 const unsigned is_the_node_in_shared_boundaries_with_other_processors =
19604 unsigned n_shd_bnd_with_other_procs_have_node = 0;
19607 if (is_the_node_in_shared_boundaries_with_other_processors == 4)
19609#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19611 <<
" In how many shared boundaries with other "
19612 <<
"processors is the node "
19618 n_shd_bnd_with_other_procs_have_node =
19622 other_processor_1.resize(n_shd_bnd_with_other_procs_have_node);
19623 other_processor_2.resize(n_shd_bnd_with_other_procs_have_node);
19624 other_shared_boundaries.resize(n_shd_bnd_with_other_procs_have_node);
19625 other_indexes.resize(n_shd_bnd_with_other_procs_have_node);
19627 for (
unsigned i = 0;
i < n_shd_bnd_with_other_procs_have_node;
i++)
19629#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19631 <<
" Processor where the other shared boundary"
19637 other_processor_1[
i] =
19640#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19642 <<
" Processor where the other shared boundary"
19648 other_processor_2[
i] =
19651#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19653 <<
" Other shared boundary id where the node is on: "
19659 other_shared_boundaries[
i] =
19662#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19664 <<
" Node index on the other shared boundary "
19679 if (is_the_node_in_shared_boundaries_with_other_processors != 0)
19681 std::ostringstream error_message;
19683 <<
"The current node is not on a shared boundary with\n"
19684 <<
"other processors, this should be indicated by a zero flag.\n"
19685 <<
"However, the read value for that flag is ("
19686 << is_the_node_in_shared_boundaries_with_other_processors <<
").\n\n";
19688 error_message.str(),
19689 "RefineableTriangleMesh::construct_new_halo_node_helper()",
19690 OOMPH_EXCEPTION_LOCATION);
19699 if (is_node_on_shared_boundary == 1)
19704 if (node_on_original_boundaries == 2)
19710 for (
unsigned i = 0;
i < n_original_boundaries_node_is_on;
i++)
19712 add_boundary_node(original_boundaries_node_is_on[
i], new_nod_pt);
19715 zeta[0] = zeta_coordinates[
i];
19716 new_nod_pt->set_coordinates_on_boundary(
19717 original_boundaries_node_is_on[
i], zeta);
19723 new_nodes_on_domain.push_back(new_nod_pt);
19726 new_el_pt->
node_pt(node_index) = new_nod_pt;
19736 bool found_node_in_other_shared_boundaries =
false;
19745 bool build_node_as_boundary_node =
false;
19747 if (is_the_node_in_shared_boundaries_with_other_processors == 4)
19750 build_node_as_boundary_node =
true;
19757 const unsigned initial_shd_bnd_id = this->initial_shared_boundary_id();
19763 for (
unsigned i = 0;
i < n_shd_bnd_with_other_procs_have_node;
i++)
19774 unsigned oproc1 = other_processor_1[
i];
19775 unsigned oproc2 = other_processor_2[
i];
19776 if (other_processor_1[
i] > other_processor_2[
i])
19778 oproc1 = other_processor_2[
i];
19779 oproc2 = other_processor_1[
i];
19784 const unsigned shd_bnd_id =
19785 other_shared_boundaries[
i] - initial_shd_bnd_id;
19788 const unsigned index = other_indexes[
i];
19792 const unsigned n_nodes_on_other_processor =
19793 other_proc_shd_bnd_node_pt[oproc1][oproc2][shd_bnd_id].size();
19795 if (n_nodes_on_other_processor > 0)
19799 std::map<unsigned, Node*>::iterator it =
19800 other_proc_shd_bnd_node_pt[oproc1][oproc2][shd_bnd_id].find(index);
19804 other_proc_shd_bnd_node_pt[oproc1][oproc2][shd_bnd_id].end())
19807 found_node_in_other_shared_boundaries =
true;
19809 Node* tmp_node_pt = (*it).second;
19812 found_node_pt.push_back(tmp_node_pt);
19823 if (found_node_in_other_shared_boundaries)
19826 const unsigned n_times_node_found = found_node_pt.size();
19827 for (
unsigned j = 1; j < n_times_node_found; j++)
19829 if (found_node_pt[j - 1] != found_node_pt[j])
19831 std::ostringstream error_message;
19833 <<
"The instances of the node that was found on\n"
19834 <<
"shared boundaries with other processors (but not\n"
19835 <<
"on shared boundaries with this processor) are not\n"
19837 <<
"These are the coordinates of the instances of the\n"
19839 <<
"(" << found_node_pt[j - 1]->x(0) <<
", "
19840 << found_node_pt[j - 1]->x(1) <<
")\n"
19841 <<
"(" << found_node_pt[j]->x(0) <<
", " << found_node_pt[j]->x(1)
19843 <<
"Dont be surprised if they are the same since the "
19844 <<
"node is\nrepeated.\n";
19846 OOMPH_CURRENT_FUNCTION,
19847 OOMPH_EXCEPTION_LOCATION);
19858 if (is_node_on_shared_boundary == 1)
19867 if (found_node_pt[0] != new_nod_pt)
19869 std::ostringstream error_message;
19871 <<
"The pointer of the node that was found to be on a\n"
19872 <<
"shared boundary with other processor(s) and the pointer\n"
19873 <<
"of the node on shared boundary with the receiver\n"
19874 <<
"processor (iproc) are not the same. This means we have a\n"
19875 <<
"repeated node)\n"
19876 <<
"The coordinates for the nodes are:\n"
19877 <<
"(" << found_node_pt[0]->x(0) <<
", " << found_node_pt[0]->x(1)
19879 <<
"(" << new_nod_pt->x(0) <<
", " << new_nod_pt->x(1) <<
")\n"
19880 <<
"Dont be surprised if they are the same since the "
19881 <<
"node is\nrepeated.\n";
19883 OOMPH_CURRENT_FUNCTION,
19884 OOMPH_EXCEPTION_LOCATION);
19895 new_nod_pt = found_node_pt[0];
19905 if (is_node_on_shared_boundary != 1)
19919 if (node_on_original_boundaries == 2 || build_node_as_boundary_node)
19923 if (!found_node_in_other_shared_boundaries)
19926 if (time_stepper_pt != 0)
19940 new_el_pt->
node_pt(node_index) = new_nod_pt;
19945 for (
unsigned i = 0;
i < n_original_boundaries_node_is_on;
i++)
19947 add_boundary_node(original_boundaries_node_is_on[
i], new_nod_pt);
19950 zeta[0] = zeta_coordinates[
i];
19951 new_nod_pt->set_coordinates_on_boundary(
19952 original_boundaries_node_is_on[
i], zeta);
19960 if (!found_node_in_other_shared_boundaries)
19963 if (time_stepper_pt != 0)
19965 new_nod_pt = new_el_pt->
construct_node(node_index, time_stepper_pt);
19975 new_el_pt->
node_pt(node_index) = new_nod_pt;
19986 new_nodes_on_domain.push_back(new_nod_pt);
19990 if (!found_node_in_other_shared_boundaries)
19993 this->add_node_pt(new_nod_pt);
20001 if (new_alg_nod_pt != 0)
20010#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
20012 <<
" Alg node update id "
20017 unsigned update_id =
20024#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
20026 <<
" Alg node # of ref values "
20030 unsigned n_ref_val =
20035 ref_value.resize(n_ref_val);
20036 for (
unsigned i_ref = 0; i_ref < n_ref_val; i_ref++)
20049#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
20051 <<
" Alg node # of geom objects "
20055 unsigned n_geom_obj =
20060 geom_object_pt.resize(n_geom_obj);
20061 for (
unsigned i_geom = 0; i_geom < n_geom_obj; i_geom++)
20063#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
20065 <<
" Alg node: geom object index "
20069 unsigned geom_index =
20082 if (!found_node_in_other_shared_boundaries)
20087 update_id, alg_mesh_pt, geom_object_pt, ref_value);
20098 if (!found_node_in_other_shared_boundaries)
20104 if (macro_nod_pt != 0)
20119 s_in_macro_node_update_element);
20123 new_el_pt, s_in_macro_node_update_element, geom_object_vector_pt);
20129 unsigned n_new_val = new_nod_pt->nvalue();
20133 if (!found_node_in_other_shared_boundaries)
20135 if (n_val > n_new_val)
20151 new std::map<unsigned, unsigned>;
20155 std::map<unsigned, unsigned>* map_pt =
20160 const unsigned id_face = 0;
20162 std::map<unsigned, unsigned>::const_iterator p =
20163 map_pt->find(id_face);
20166 if (p == map_pt->end())
20170 (*map_pt)[id_face] = n_new_val;
20173 new_nod_pt->resize(n_val);
20182 if (solid_nod_pt != 0)
20185 for (
unsigned i_val = 0; i_val < n_solid_val; i_val++)
20187 for (
unsigned t = 0;
t < n_prev;
t++)
20194 if (!found_node_in_other_shared_boundaries)
20197 t, i_val, read_data);
20202#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
20204 <<
" Number of values solid node: "
20208 const unsigned nvalues_solid_node =
20211 for (
unsigned i = 0;
i < nvalues_solid_node;
i++)
20213 values_solid_node[
i] =
20219 if (!found_node_in_other_shared_boundaries)
20221 unsigned index = 0;
20228 for (
unsigned i_val = 0; i_val < n_val; i_val++)
20230 for (
unsigned t = 0;
t < n_prev;
t++)
20238 if (!found_node_in_other_shared_boundaries)
20240 new_nod_pt->set_value(
t, i_val, read_data);
20246 unsigned n_dim = new_nod_pt->ndim();
20247 for (
unsigned idim = 0; idim < n_dim; idim++)
20249 for (
unsigned t = 0;
t < n_prev;
t++)
20257 if (!found_node_in_other_shared_boundaries)
20260 new_nod_pt->x(
t, idim) = read_data;
20272 if (n_shd_bnd_with_other_procs_have_node > 0 &&
20276 !found_node_in_other_shared_boundaries)
20284 this->update_other_proc_shd_bnd_node_helper(new_nod_pt,
20285 other_proc_shd_bnd_node_pt,
20288 other_shared_boundaries,
20291 node_name_to_global_index,
20292 global_shared_node_pt);
20301 template<
class ELEMENT>
20303 Node*& new_node_pt,
20305 other_proc_shd_bnd_node_pt,
20316 const unsigned initial_shd_bnd_id = this->initial_shared_boundary_id();
20321 const unsigned n_data = other_processor_1.size();
20326 node_name[0] = other_processor_1[0];
20327 node_name[1] = other_processor_2[0];
20328 node_name[2] = other_shared_boundaries[0];
20329 node_name[3] = other_indexes[0];
20333 std::map<Vector<unsigned>,
unsigned>::iterator it =
20334 node_name_to_global_index.find(node_name);
20335 if (it == node_name_to_global_index.end())
20337 std::ostringstream error_stream;
20338 error_stream <<
"The node name does not exist in the global node names\n"
20339 <<
"This is the name of the node\n"
20340 <<
"Name: iproc, jproc, ishd_bnd, idx\n"
20341 <<
"Name: " << node_name[0] <<
", " << node_name[1] <<
", "
20342 << node_name[2] <<
", " << node_name[3] <<
"\n";
20344 error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
20349 const unsigned iglobal_node = node_name_to_global_index[node_name];
20351 global_shared_node_pt[iglobal_node] = new_node_pt;
20355 const unsigned n_names = inode_names.size();
20360 unsigned n_found_node_names_on_global_node_name = 0;
20362 for (
unsigned j = 0; j < n_data; j++)
20365 for (
unsigned k = 0; k < n_names; k++)
20368 if (inode_names[k][0] == other_processor_1[j] &&
20369 inode_names[k][1] == other_processor_2[j] &&
20370 inode_names[k][2] == other_shared_boundaries[j] &&
20371 inode_names[k][3] == other_indexes[j])
20375 n_found_node_names_on_global_node_name++;
20383 if (n_found_node_names_on_global_node_name != n_data)
20385 std::ostringstream error_stream;
20387 <<
"Not all the node names of the current node were found on the\n"
20388 <<
"global node names. This happened when adding the node pointer\n"
20389 <<
"to the data structure that keeps tracks of nodes on shared\n"
20390 <<
"boundaries with other processors\n\n"
20391 <<
"These are the names of the current node\n"
20392 <<
"Name k: iproc, jproc, ishd_bnd, idx\n";
20393 for (
unsigned j = 0; j < n_data; j++)
20395 error_stream <<
"Name(" << j <<
"): " << other_processor_1[j] <<
", "
20396 << other_processor_2[j] <<
", "
20397 << other_shared_boundaries[j] <<
", " << other_indexes[j]
20401 error_stream <<
"\n\nThese are the names of the global node\n"
20402 <<
"Name k: iproc, jproc, ishd_bnd, idx\n";
20403 for (
unsigned k = 0; k < n_names; k++)
20405 error_stream <<
"Name(" << k <<
"): " << inode_names[k][0] <<
", "
20406 << inode_names[k][1] <<
", " << inode_names[k][2] <<
", "
20407 << inode_names[k][3] <<
"\n";
20411 error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
20416 for (
unsigned j = 0; j < n_names; j++)
20419 const unsigned iproc = inode_names[j][0];
20420 const unsigned jproc = inode_names[j][1];
20421 const unsigned ishd_bnd = inode_names[j][2] - initial_shd_bnd_id;
20422 const unsigned index = inode_names[j][3];
20428 other_proc_shd_bnd_node_pt[iproc][jproc][ishd_bnd][index] = new_node_pt;
20432 other_proc_shd_bnd_node_pt[jproc][iproc][ishd_bnd][index] = new_node_pt;
20450 template<
class ELEMENT>
20454 oomph_info <<
"Load balance (unstructured mesh) [BEGIN]" << std::endl;
20458 if (!this->is_mesh_distributed())
20460 std::ostringstream warning_message;
20462 <<
"\n===============================================================\n"
20463 <<
"The load balancing can only be performed in distributed meshes,\n"
20464 <<
"your mesh has not been distributed.\n"
20465 <<
"==============================================================="
20468 OOMPH_CURRENT_FUNCTION,
20469 OOMPH_EXCEPTION_LOCATION);
20475 const unsigned nproc = this->communicator_pt()->nproc();
20477 const unsigned my_rank = this->communicator_pt()->my_rank();
20482 std::ostringstream warning_message;
20484 <<
"\n===============================================================\n"
20485 <<
"The load balancing can only be performed when there are at least\n"
20486 <<
"two procesors, the current number of processors is one.\n"
20487 <<
"==============================================================="
20490 OOMPH_CURRENT_FUNCTION,
20491 OOMPH_EXCEPTION_LOCATION);
20497 double t_start_overall_load_balance = 0.0;
20498 if (Print_timings_level_load_balance > 1)
20504 const unsigned nelement_before_load_balance = this->nelement();
20509 if (nnon_halo_element() != target_domain_for_local_non_halo_element.size())
20511 std::ostringstream error_message;
20512 error_message <<
"The number of non halo elements in the current mesh ("
20513 << nnon_halo_element() <<
") and the number\n"
20514 <<
"of target areas for the local non halo elements ("
20515 << target_domain_for_local_non_halo_element.size()
20516 <<
") is different\n\n";
20518 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
20524 for (
unsigned e = 0;
e < nelement_before_load_balance;
e++)
20526 backed_up_ele_pt[
e] = this->finite_element_pt(
e);
20534 double tt_start_get_domains_halo_elements = 0.0;
20535 if (Print_timings_level_load_balance > 1)
20558 for (
unsigned iproc = 0; iproc < nproc; iproc++)
20562 if (iproc != my_rank)
20565 const unsigned n_halo_iproc = this->nroot_halo_element(iproc);
20567 new_domains_halo_elements[iproc].resize(n_halo_iproc);
20570 const unsigned n_haloed_iproc = this->nroot_haloed_element(iproc);
20572 new_domains_haloed_elements[iproc].resize(n_haloed_iproc);
20585 for (
unsigned iproc = 0; iproc < nproc; iproc++)
20589 if (iproc != my_rank)
20592 const unsigned n_haloed_iproc = this->nroot_haloed_element(iproc);
20595 for (
unsigned ihd = 0; ihd < n_haloed_iproc; ihd++)
20599 this->root_haloed_element_pt(iproc, ihd);
20602 unsigned nh_count4 = 0;
20604 for (
unsigned e = 0;
e < nelement_before_load_balance;
e++)
20616 if (ele_pt == haloed_ele_pt)
20619 const unsigned element_domain =
20620 target_domain_for_local_non_halo_element[nh_count4 - 1];
20625 new_domains_haloed_elements[iproc][ihd] = element_domain;
20628 counter_for_found_haloed_elements[iproc]++;
20649 for (
unsigned iproc = 0; iproc < nproc; iproc++)
20653 if (iproc != my_rank)
20656 const unsigned n_haloed_iproc = this->nroot_haloed_element(iproc);
20660 if (n_haloed_iproc != counter_for_found_haloed_elements[iproc])
20662 std::ostringstream error_message;
20663 error_message <<
"The independent counting of found haloed elements ("
20664 << counter_for_found_haloed_elements[iproc]
20665 <<
") with processor (" << iproc
20666 <<
") is not equal to the number of haloed elements ("
20667 << n_haloed_iproc <<
") with processor (" << iproc
20670 OOMPH_CURRENT_FUNCTION,
20671 OOMPH_EXCEPTION_LOCATION);
20689 for (
unsigned iproc = 0; iproc < nproc; iproc++)
20693 if (iproc != my_rank)
20696 const unsigned n_haloed_ele_iproc = this->nroot_haloed_element(iproc);
20698 nhaloed_elements_with_iproc[iproc] = n_haloed_ele_iproc;
20701 for (
unsigned i = 0;
i < n_haloed_ele_iproc;
i++)
20703 new_domains_haloed_flat_unsigned.push_back(
20704 new_domains_haloed_elements[iproc][
i]);
20712 Vector<int> offset_haloed_elements_with_iproc(nproc);
20713 offset_haloed_elements_with_iproc[0] = 0;
20714 for (
unsigned ip = 1; ip < nproc; ip++)
20717 offset_haloed_elements_with_iproc[ip] =
20718 offset_haloed_elements_with_iproc[ip - 1] +
20719 nhaloed_elements_with_iproc[ip - 1];
20728 unsigned counter_halo_ele_with_all_procs = 0;
20735 for (
unsigned iproc = 0; iproc < nproc; iproc++)
20739 if (iproc != my_rank)
20742 const unsigned n_halo_ele_iproc = this->nroot_halo_element(iproc);
20744 nhalo_elements_with_iproc[iproc] = n_halo_ele_iproc;
20746 counter_halo_ele_with_all_procs += n_halo_ele_iproc;
20752 Vector<int> offset_halo_elements_with_iproc(nproc);
20753 offset_halo_elements_with_iproc[0] = 0;
20754 for (
unsigned ip = 1; ip < nproc; ip++)
20757 offset_halo_elements_with_iproc[ip] =
20758 offset_halo_elements_with_iproc[ip - 1] +
20759 nhalo_elements_with_iproc[ip - 1];
20768 counter_halo_ele_with_all_procs);
20772 MPI_Alltoallv(&new_domains_haloed_flat_unsigned[0],
20773 &nhaloed_elements_with_iproc[0],
20774 &offset_haloed_elements_with_iproc[0],
20776 &new_domains_halo_flat_unsigned[0],
20777 &nhalo_elements_with_iproc[0],
20778 &offset_halo_elements_with_iproc[0],
20780 this->communicator_pt()->mpi_comm());
20786 unsigned counter_new_domains_halo_ele = 0;
20787 for (
unsigned iproc = 0; iproc < nproc; iproc++)
20791 if (iproc != my_rank)
20794 const unsigned ntmp_halo_elements_with_iproc =
20795 nhalo_elements_with_iproc[iproc];
20798 for (
unsigned i = 0;
i < ntmp_halo_elements_with_iproc;
i++)
20802 new_domains_halo_elements[iproc][
i] =
20803 new_domains_halo_flat_unsigned[counter_new_domains_halo_ele++];
20809 if (Print_timings_level_load_balance > 1)
20811 oomph_info <<
"CPU for getting domains halo elements (load balance) [1]: "
20827 double tt_start_get_fe_version_from_ge_halo_ed = 0.0;
20828 if (Print_timings_level_load_balance > 1)
20838 for (
unsigned iproc = 0; iproc < nproc; iproc++)
20841 if (iproc != my_rank)
20844 const unsigned nhalo_ele_iproc = this->nroot_halo_element(iproc);
20847 this->root_halo_element_pt(iproc);
20849 f_halo_element_pt[iproc].resize(nhalo_ele_iproc);
20851 for (
unsigned ih = 0; ih < nhalo_ele_iproc; ih++)
20857 f_halo_element_pt[iproc][ih] = ele_pt;
20861 const unsigned nhaloed_ele_iproc = this->nroot_haloed_element(iproc);
20864 this->root_haloed_element_pt(iproc);
20866 f_haloed_element_pt[iproc].resize(nhaloed_ele_iproc);
20868 for (
unsigned ihd = 0; ihd < nhaloed_ele_iproc; ihd++)
20872 dynamic_cast<FiniteElement*
>(haloed_element_pt_iproc[ihd]);
20874 f_haloed_element_pt[iproc][ihd] = ele_pt;
20883 if (Print_timings_level_load_balance > 1)
20885 oomph_info <<
"CPU for getting finite element versions from generalised "
20886 "halo(ed) elements (load balance) [2]: "
20888 tt_start_get_fe_version_from_ge_halo_ed
20905 double tt_start_prepare_element_to_send = 0.0;
20906 if (Print_timings_level_load_balance > 1)
20916 std::map<Data*, std::set<unsigned>>
20917 processors_associated_with_data_before_load_balance;
20921 unsigned nh_count3 = 0;
20922 for (
unsigned e = 0;
e < nelement_before_load_balance;
e++)
20930 const unsigned element_domain =
20931 target_domain_for_local_non_halo_element[nh_count3++];
20934 elements_to_send_pt[element_domain].push_back(ele_pt);
20937 const unsigned n_nodes = ele_pt->
nnode();
20939 for (
unsigned j = 0; j < n_nodes; j++)
20942 Node* node_pt = ele_pt->
node_pt(j);
20944 processors_associated_with_data_before_load_balance[node_pt].insert(
20957 for (
unsigned iproc = 0; iproc < nproc; iproc++)
20960 if (iproc != my_rank)
20963 const unsigned n_halo_ele_iproc = this->nroot_halo_element(iproc);
20966 this->root_halo_element_pt(iproc);
20968 for (
unsigned ih = 0; ih < n_halo_ele_iproc; ih++)
20971 const unsigned element_domain = new_domains_halo_elements[iproc][ih];
20978 const unsigned n_nodes = ele_pt->
nnode();
20980 for (
unsigned j = 0; j < n_nodes; j++)
20983 Node* node_pt = ele_pt->
node_pt(j);
20986 processors_associated_with_data_before_load_balance[node_pt].insert(
20998 if (Print_timings_level_load_balance > 1)
21000 oomph_info <<
"CPU for preparing elements to send to other processors "
21001 "(load balance) [3]: "
21025 double tt_start_compute_new_local_halo_elements = 0.0;
21026 if (Print_timings_level_load_balance > 1)
21061 for (
unsigned iproc = 0; iproc < nproc; iproc++)
21064 new_local_halo_element_pt[iproc].resize(nproc);
21073 unsigned nh_count5 = 0;
21074 for (
unsigned e = 0;
e < nelement_before_load_balance;
e++)
21082 const unsigned ele_domain =
21083 target_domain_for_local_non_halo_element[nh_count5++];
21086 if (ele_domain != iproc)
21089 const unsigned nnodes = ele_pt->
nnode();
21091 for (
unsigned j = 0; j < nnodes; j++)
21093 Node* node_pt = ele_pt->
node_pt(j);
21096 std::set<unsigned>::iterator it =
21097 processors_associated_with_data_before_load_balance[node_pt]
21101 processors_associated_with_data_before_load_balance[node_pt]
21108 if (!new_local_halo_already_added[ele_domain][ele_pt])
21112 new_local_halo_element_pt[iproc][ele_domain].push_back(
21115 new_local_halo_already_added[ele_domain][ele_pt] =
true;
21153 for (
unsigned jproc = 0; jproc < nproc; jproc++)
21157 if (jproc != my_rank)
21160 const unsigned n_halo_ele_jproc = this->nroot_halo_element(jproc);
21163 this->root_halo_element_pt(jproc);
21166 for (
unsigned jh = 0; jh < n_halo_ele_jproc; jh++)
21169 const unsigned ele_domain = new_domains_halo_elements[jproc][jh];
21200 if (ele_domain != iproc)
21206 const unsigned nnodes = ele_pt->
nnode();
21208 for (
unsigned j = 0; j < nnodes; j++)
21211 Node* node_pt = ele_pt->
node_pt(j);
21215 std::set<unsigned>::iterator it =
21216 processors_associated_with_data_before_load_balance[node_pt]
21220 processors_associated_with_data_before_load_balance[node_pt]
21228 if (!new_local_halo_already_added[ele_domain][ele_pt])
21232 new_local_halo_element_pt[iproc][ele_domain].push_back(
21234 new_local_halo_already_added[ele_domain][ele_pt] =
true;
21263 if (Print_timings_level_load_balance > 1)
21266 <<
"CPU for computing new local halo elements (load balance) [4]: "
21286 double tt_start_compute_new_local_shd_bnd_ele = 0.0;
21287 if (Print_timings_level_load_balance > 1)
21295 new_local_halo_shared_boundary_element_pt(nproc);
21297 new_local_halo_shared_boundary_element_face_index(nproc);
21300 for (
unsigned iproc = 0; iproc < nproc; iproc++)
21302 new_local_halo_shared_boundary_element_pt[iproc].resize(nproc);
21303 new_local_halo_shared_boundary_element_face_index[iproc].resize(nproc);
21311 for (
unsigned iproc = 0; iproc < nproc; iproc++)
21317 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
21319 this->get_shared_boundary_elements_and_face_indexes(
21320 new_local_halo_element_pt[iproc][jproc],
21321 new_local_halo_element_pt[jproc][iproc],
21322 new_local_halo_shared_boundary_element_pt[iproc][jproc],
21323 new_local_halo_shared_boundary_element_face_index[iproc][jproc],
21324 new_local_halo_shared_boundary_element_pt[jproc][iproc],
21325 new_local_halo_shared_boundary_element_face_index[jproc][iproc]);
21330 if (Print_timings_level_load_balance > 1)
21332 oomph_info <<
"CPU for computing new local shared boundary elements "
21333 "(load balance) [5]: "
21335 tt_start_compute_new_local_shd_bnd_ele
21354 double tt_start_send_elements_to_other_processors = 0.0;
21355 if (Print_timings_level_load_balance > 1)
21363 this->sort_nodes_on_shared_boundaries();
21374 new_received_haloed_shared_boundary_element_pt(nproc);
21376 new_received_haloed_shared_boundary_element_face_index(nproc);
21382 other_proc_shd_bnd_node_pt(nproc);
21384 for (
unsigned iproc = 0; iproc < nproc; iproc++)
21387 other_proc_shd_bnd_node_pt[iproc].resize(nproc);
21388 for (
unsigned jproc = 0; jproc < nproc; jproc++)
21391 const unsigned initial_shd_bnd_id = this->initial_shared_boundary_id();
21392 const unsigned final_shd_bnd_id = this->final_shared_boundary_id();
21393 const unsigned n_shared_bound = final_shd_bnd_id - initial_shd_bnd_id;
21394 other_proc_shd_bnd_node_pt[iproc][jproc].resize(n_shared_bound);
21407 std::map<Vector<unsigned>,
unsigned> node_name_to_global_index;
21415 compute_global_node_names_and_shared_nodes(other_proc_shd_bnd_node_pt,
21417 node_name_to_global_index,
21418 global_shared_node_pt);
21424 received_old_haloed_element_pt(nproc);
21431 for (
unsigned iproc = 0; iproc < nproc; iproc++)
21433 received_old_haloed_element_pt[iproc].resize(nproc);
21438 for (
unsigned iproc = 0; iproc < nproc; iproc++)
21440 if (iproc != my_rank)
21454#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
21459 const unsigned nelements_to_send = elements_to_send_pt[iproc].size();
21466#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
21467 std::stringstream junk;
21468 junk <<
"Number of elements to send from processor " << my_rank
21469 <<
" to processor " << iproc <<
": (" << nelements_to_send <<
")";
21474 for (
unsigned e = 0;
e < nelements_to_send;
e++)
21480 const unsigned ncurrently_sent_elements =
21481 currently_sent_elements.size();
21484 const unsigned index_ele = try_to_add_element_pt_load_balance(
21485 currently_sent_elements, send_ele_pt);
21488 if (index_ele == ncurrently_sent_elements)
21491#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
21493 "Element needs to be constructed");
21497 get_required_elemental_information_load_balance_helper(
21498 iproc, f_haloed_element_pt, send_ele_pt);
21501 const unsigned nnodes = send_ele_pt->
nnode();
21504 for (
unsigned j = 0; j < nnodes; j++)
21506 Node* node_pt = send_ele_pt->
node_pt(j);
21509 add_node_load_balance_helper(iproc,
21511 currently_sent_nodes,
21520#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
21524#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
21544 for (
unsigned jproc = 0; jproc < nproc; jproc++)
21550 const unsigned njproc_iproc_new_local_halo_shared_boundary_ele =
21551 new_local_halo_shared_boundary_element_pt[jproc][iproc].size();
21558 unsigned nfound_new_local_halo_shared_bound_ele_index = 0;
21561 unsigned nnon_halo_new_local_halo_shared_bound_ele = 0;
21565 for (
unsigned e = 0;
21566 e < njproc_iproc_new_local_halo_shared_boundary_ele;
21571 new_local_halo_shared_boundary_element_pt[jproc][iproc][
e];
21575 if (!shared_ele_pt->
is_halo())
21577 nnon_halo_new_local_halo_shared_bound_ele++;
21582 const unsigned ncurrently_sent_elements =
21583 currently_sent_elements.size();
21585 for (
unsigned ics = 0; ics < ncurrently_sent_elements; ics++)
21588 currently_sent_elements[ics];
21591 if (currently_sent_ele_pt == shared_ele_pt)
21595 new_local_halo_shared_boundary_ele_index.push_back(ics);
21598 nfound_new_local_halo_shared_bound_ele_index++;
21610 if (nfound_new_local_halo_shared_bound_ele_index !=
21611 nnon_halo_new_local_halo_shared_bound_ele)
21613 std::ostringstream error_message;
21614 error_message <<
"Was only possible to identify ("
21615 << nfound_new_local_halo_shared_bound_ele_index
21617 << nnon_halo_new_local_halo_shared_bound_ele
21619 <<
"elements between\nprocessor (" << iproc
21620 <<
") and (" << jproc <<
") "
21621 <<
"when sending elements to processor (" << iproc
21624 OOMPH_CURRENT_FUNCTION,
21625 OOMPH_EXCEPTION_LOCATION);
21631#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
21632 std::stringstream junk;
21633 junk <<
"Flag for synchronisation 9999";
21640 nnon_halo_new_local_halo_shared_bound_ele);
21641#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
21642 std::stringstream junk2;
21643 junk2 <<
"Number of new local halo shared boundary elements "
21644 << nnon_halo_new_local_halo_shared_bound_ele;
21650 unsigned counter_nonhalo_sent = 0;
21653 for (
unsigned e = 0;
21654 e < njproc_iproc_new_local_halo_shared_boundary_ele;
21659 new_local_halo_shared_boundary_element_pt[jproc][iproc][
e];
21663 if (!shared_ele_pt->
is_halo())
21667 const unsigned ele_index =
21668 new_local_halo_shared_boundary_ele_index
21669 [counter_nonhalo_sent++];
21671 const unsigned face_index =
21672 new_local_halo_shared_boundary_element_face_index[jproc][iproc]
21678#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
21679 std::stringstream junk;
21680 junk <<
"The index of the halo shared boundary element "
21688#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
21689 std::stringstream junk2;
21690 junk2 <<
"The face index of the halo shared boundary element "
21705 int send_proc =
static_cast<int>(iproc);
21707 int recv_proc =
static_cast<int>(iproc);
21708 send_and_receive_elements_nodes_info(send_proc, recv_proc);
21723#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
21725 <<
" Number of elements need to be constructed "
21731 const unsigned nelements_to_create =
21734 for (
unsigned e = 0;
e < nelements_to_create;
e++)
21738 create_element_load_balance_helper(iproc,
21739 f_haloed_element_pt,
21740 received_old_haloed_element_pt,
21741 currently_created_elements,
21742 currently_created_nodes,
21743 other_proc_shd_bnd_node_pt,
21745 node_name_to_global_index,
21746 global_shared_node_pt);
21752 const unsigned nreceived_elements = currently_created_elements.size();
21753 received_elements_pt[iproc].resize(nreceived_elements);
21754 for (
unsigned e = 0;
e < nreceived_elements;
e++)
21756 received_elements_pt[iproc][
e] = currently_created_elements[
e];
21763 new_received_haloed_shared_boundary_element_pt[iproc].resize(nproc);
21764 new_received_haloed_shared_boundary_element_face_index[iproc].resize(
21768 for (
unsigned jproc = 0; jproc < nproc; jproc++)
21771 const unsigned synchronisation_flag =
21774 if (synchronisation_flag != 9999)
21776 std::ostringstream error_message;
21777 error_message <<
"The synchronisation flag was not read, the\n"
21778 <<
"information sent between processor (" << my_rank
21780 <<
"and (" << iproc
21781 <<
")\nis no longer synchronised\n\n";
21783 OOMPH_CURRENT_FUNCTION,
21784 OOMPH_EXCEPTION_LOCATION);
21790 const unsigned niproc_jproc_new_received_haloed_shared_boundary_ele =
21794 for (
unsigned e = 0;
21795 e < niproc_jproc_new_received_haloed_shared_boundary_ele;
21800 const unsigned ele_index =
21804 const unsigned face_index =
21809 currently_created_elements[ele_index];
21814 new_received_haloed_shared_boundary_element_pt[iproc][jproc]
21815 .push_back(shared_ele_pt);
21817 new_received_haloed_shared_boundary_element_face_index[iproc][jproc]
21818 .push_back(face_index);
21829 if (Print_timings_level_load_balance > 1)
21831 oomph_info <<
"CPU for sending elements to their new processors (load "
21834 tt_start_send_elements_to_other_processors
21853 double tt_start_compute_additional_shared_boundaries = 0.0;
21854 if (Print_timings_level_load_balance > 1)
21891 for (
unsigned iproc = 0; iproc < nproc; iproc++)
21893 if (my_rank < iproc)
21896 this->get_shared_boundary_elements_and_face_indexes(
21897 received_elements_pt[iproc],
21898 elements_to_send_pt[iproc],
21899 tmp_group1_shared_boundary_element_pt[iproc],
21900 tmp_group1_shared_boundary_element_face_index[iproc],
21901 tmp_group2_shared_boundary_element_pt[iproc],
21902 tmp_group2_shared_boundary_element_face_index[iproc]);
21905 else if (my_rank > iproc)
21908 this->get_shared_boundary_elements_and_face_indexes(
21909 elements_to_send_pt[iproc],
21910 received_elements_pt[iproc],
21911 tmp_group1_shared_boundary_element_pt[iproc],
21912 tmp_group1_shared_boundary_element_face_index[iproc],
21913 tmp_group2_shared_boundary_element_pt[iproc],
21914 tmp_group2_shared_boundary_element_face_index[iproc]);
21921 if (Print_timings_level_load_balance > 1)
21924 <<
"CPU for computing additional shared boundaries (load balance) [7]: "
21926 tt_start_compute_additional_shared_boundaries
21945 double tt_start_sort_shared_boundaries = 0.0;
21946 if (Print_timings_level_load_balance > 1)
21971 for (
unsigned iproc = 0; iproc < nproc; iproc++)
21974 if (my_rank < iproc)
21978 for (
unsigned jproc = 0; jproc < nproc; jproc++)
21981 if (jproc != my_rank)
21984 const unsigned nrecvd_haloed_shared_bound_ele_jproc_iproc =
21985 new_received_haloed_shared_boundary_element_pt[jproc][iproc]
21987 for (
unsigned e = 0;
e < nrecvd_haloed_shared_bound_ele_jproc_iproc;
21992 new_received_haloed_shared_boundary_element_pt[jproc][iproc][
e];
21994 const unsigned face_index =
21995 new_received_haloed_shared_boundary_element_face_index[jproc]
22000 new_shared_boundary_element_pt[iproc].push_back(ele_pt);
22001 new_shared_boundary_element_face_index[iproc].push_back(
22012 const unsigned nlocal_haloed_shared_bound_ele_iproc_my_rank =
22013 new_local_halo_shared_boundary_element_pt[iproc][my_rank].size();
22014 for (
unsigned e = 0;
e < nlocal_haloed_shared_bound_ele_iproc_my_rank;
22019 new_local_halo_shared_boundary_element_pt[iproc][my_rank][
e];
22021 const unsigned face_index =
22022 new_local_halo_shared_boundary_element_face_index[iproc][my_rank]
22031 new_shared_boundary_element_pt[iproc].push_back(ele_pt);
22032 new_shared_boundary_element_face_index[iproc].push_back(face_index);
22039 const unsigned ntmp_group1_shared_bound_ele_iproc =
22040 tmp_group1_shared_boundary_element_pt[iproc].size();
22041 for (
unsigned e = 0;
e < ntmp_group1_shared_bound_ele_iproc;
e++)
22045 tmp_group1_shared_boundary_element_pt[iproc][
e];
22047 const unsigned face_index =
22048 tmp_group1_shared_boundary_element_face_index[iproc][
e];
22051 new_shared_boundary_element_pt[iproc].push_back(ele_pt);
22052 new_shared_boundary_element_face_index[iproc].push_back(face_index);
22058 else if (my_rank > iproc)
22066 const unsigned nlocal_haloed_shared_bound_ele_iproc_my_rank =
22067 new_local_halo_shared_boundary_element_pt[iproc][my_rank].size();
22068 for (
unsigned e = 0;
e < nlocal_haloed_shared_bound_ele_iproc_my_rank;
22073 new_local_halo_shared_boundary_element_pt[iproc][my_rank][
e];
22075 const unsigned face_index =
22076 new_local_halo_shared_boundary_element_face_index[iproc][my_rank]
22085 new_shared_boundary_element_pt[iproc].push_back(ele_pt);
22086 new_shared_boundary_element_face_index[iproc].push_back(face_index);
22091 for (
unsigned jproc = 0; jproc < nproc; jproc++)
22094 if (jproc != my_rank)
22098 const unsigned nrecvd_haloed_shared_bound_ele_jproc_iproc =
22099 new_received_haloed_shared_boundary_element_pt[jproc][iproc]
22101 for (
unsigned e = 0;
e < nrecvd_haloed_shared_bound_ele_jproc_iproc;
22106 new_received_haloed_shared_boundary_element_pt[jproc][iproc][
e];
22108 const unsigned face_index =
22109 new_received_haloed_shared_boundary_element_face_index[jproc]
22114 new_shared_boundary_element_pt[iproc].push_back(ele_pt);
22115 new_shared_boundary_element_face_index[iproc].push_back(
22126 const unsigned ntmp_group2_shared_bound_ele_iproc =
22127 tmp_group2_shared_boundary_element_pt[iproc].size();
22128 for (
unsigned e = 0;
e < ntmp_group2_shared_bound_ele_iproc;
e++)
22132 tmp_group2_shared_boundary_element_pt[iproc][
e];
22134 const unsigned face_index =
22135 tmp_group2_shared_boundary_element_face_index[iproc][
e];
22138 new_shared_boundary_element_pt[iproc].push_back(ele_pt);
22139 new_shared_boundary_element_face_index[iproc].push_back(face_index);
22148 if (Print_timings_level_load_balance > 1)
22150 oomph_info <<
"CPU for sorting shared boundaries (load balance) [8]: "
22172 double tt_start_create_new_shared_boundaries = 0.0;
22173 if (Print_timings_level_load_balance > 1)
22186 std::set<FiniteElement*> element_in_processor_pt;
22190 unsigned nh_count6 = 0;
22191 for (
unsigned e = 0;
e < nelement_before_load_balance;
e++)
22199 if (target_domain_for_local_non_halo_element[nh_count6++] == my_rank)
22202 element_in_processor_pt.insert(ele_pt);
22211 for (
unsigned iproc = 0; iproc < nproc; iproc++)
22214 if (iproc != my_rank)
22218 const unsigned n_received_ele = received_elements_pt[iproc].size();
22219 for (
unsigned ie = 0; ie < n_received_ele; ie++)
22225 element_in_processor_pt.insert(ele_pt);
22234 create_new_shared_boundaries(element_in_processor_pt,
22235 new_shared_boundary_element_pt,
22236 new_shared_boundary_element_face_index);
22239 if (Print_timings_level_load_balance > 1)
22242 <<
"CPU for creating new shared boundaries (load balance) [9]: "
22265 double tt_start_delete_elements = 0.0;
22266 if (Print_timings_level_load_balance > 1)
22279 this->Halo_node_pt.clear();
22280 this->Root_halo_element_pt.clear();
22282 this->Haloed_node_pt.clear();
22283 this->Root_haloed_element_pt.clear();
22286 const unsigned nnodes = this->nnode();
22287 for (
unsigned j = 0; j < nnodes; j++)
22289 this->node_pt(j)->set_obsolete();
22293 this->flush_element_storage();
22296 this->delete_all_external_storage();
22299 this->External_halo_node_pt.clear();
22300 this->External_halo_element_pt.clear();
22302 this->External_haloed_node_pt.clear();
22303 this->External_haloed_element_pt.clear();
22309 unsigned nh_count7 = 0;
22310 for (
unsigned e = 0;
e < nelement_before_load_balance;
e++)
22316 if (target_domain_for_local_non_halo_element[nh_count7++] == my_rank)
22319 this->add_element_pt(ele_pt);
22321 const unsigned nele_nodes = ele_pt->
nnode();
22323 for (
unsigned j = 0; j < nele_nodes; j++)
22326 ele_pt->
node_pt(j)->set_non_obsolete();
22333 deleted_elements.push_back(ele_pt);
22343 deleted_elements.push_back(ele_pt);
22352 for (
unsigned iproc = 0; iproc < nproc; iproc++)
22354 if (iproc != my_rank)
22358 const unsigned nreceived_ele = received_elements_pt[iproc].size();
22359 for (
unsigned ie = 0; ie < nreceived_ele; ie++)
22364 this->add_element_pt(ele_pt);
22366 const unsigned nele_nodes = ele_pt->
nnode();
22368 for (
unsigned j = 0; j < nele_nodes; j++)
22371 ele_pt->
node_pt(j)->set_non_obsolete();
22381 this->prune_dead_nodes();
22384 if (Print_timings_level_load_balance > 1)
22386 oomph_info <<
"CPU for deleting elements no longer belonging to this "
22387 "processor (load balance) [10]: "
22406 double tt_start_re_etablish_halo_ed_info = 0.0;
22407 if (Print_timings_level_load_balance > 1)
22416 this->sort_nodes_on_shared_boundaries();
22423 const unsigned tmp_nboundary = this->nboundary();
22429 const unsigned n_regions = this->nregion();
22432 for (
unsigned ib = 0; ib < tmp_nboundary; ib++)
22435 ntmp_boundary_elements[ib] = this->nboundary_element(ib);
22438 ntmp_boundary_elements_in_region[ib].resize(n_regions);
22441 for (
unsigned rr = 0; rr < n_regions; rr++)
22444 const unsigned region_id =
22445 static_cast<unsigned>(this->region_attribute(rr));
22450 ntmp_boundary_elements_in_region[ib][rr] =
22451 this->nboundary_element_in_region(ib, region_id);
22458 this->reset_halo_haloed_scheme();
22461 const unsigned nelement_after_load_balance = this->nelement();
22465 this->reset_boundary_element_info(ntmp_boundary_elements,
22466 ntmp_boundary_elements_in_region,
22492 for (
unsigned b = 0; b < tmp_nboundary; b++)
22494 if (this->boundary_geom_object_pt(b) != 0)
22497 this->flush_boundary_segment_node(b);
22503 get_boundary_segment_nodes_helper(b, dummy_segment_node_pt);
22506 const unsigned nsegments = dummy_segment_node_pt.size();
22510 this->set_nboundary_segment_node(b, nsegments);
22516 if (Print_timings_level_load_balance > 1)
22519 <<
"CPU for re-establishing halo(ed) information (load balance) [11]: "
22531 if (Print_timings_level_load_balance > 1)
22533 oomph_info <<
"CPU for load balance [n_ele_before="
22534 << nelement_before_load_balance
22535 <<
", n_ele_after=" << nelement_after_load_balance <<
"]: "
22540 oomph_info <<
"Load balance (unstructured mesh) [END]" << std::endl;
22548 template<
class ELEMENT>
22564 const unsigned nfirst_element = first_element_pt.size();
22566 for (
unsigned ef = 0; ef < nfirst_element; ef++)
22571 bool first_ele_is_halo =
false;
22574 first_ele_is_halo =
true;
22577 for (
unsigned ifface = 0; ifface < 3; ifface++)
22582 first_face[0] = fele_pt->
node_pt(1);
22583 first_face[1] = fele_pt->
node_pt(2);
22585 else if (ifface == 1)
22587 first_face[0] = fele_pt->
node_pt(2);
22588 first_face[1] = fele_pt->
node_pt(0);
22590 else if (ifface == 2)
22592 first_face[0] = fele_pt->
node_pt(0);
22593 first_face[1] = fele_pt->
node_pt(1);
22600 const unsigned nsecond_element = second_element_pt.size();
22602 for (
unsigned es = 0; es < nsecond_element; es++)
22607 bool second_ele_is_halo =
false;
22610 second_ele_is_halo =
true;
22617 if (!(first_ele_is_halo && second_ele_is_halo))
22620 for (
unsigned isface = 0; isface < 3; isface++)
22625 second_face[0] = sele_pt->
node_pt(1);
22626 second_face[1] = sele_pt->
node_pt(2);
22628 else if (isface == 1)
22630 second_face[0] = sele_pt->
node_pt(2);
22631 second_face[1] = sele_pt->
node_pt(0);
22633 else if (isface == 2)
22635 second_face[0] = sele_pt->
node_pt(0);
22636 second_face[1] = sele_pt->
node_pt(1);
22641 if (first_face[0] == second_face[0] &&
22642 first_face[1] == second_face[1])
22645 first_shared_boundary_element_pt.push_back(fele_pt);
22647 first_shared_boundary_element_face_index.push_back(ifface);
22650 second_shared_boundary_element_pt.push_back(sele_pt);
22652 second_shared_boundary_element_face_index.push_back(isface);
22660 es = nsecond_element;
22663 else if (first_face[0] == second_face[1] &&
22664 first_face[1] == second_face[0])
22667 first_shared_boundary_element_pt.push_back(fele_pt);
22669 first_shared_boundary_element_face_index.push_back(ifface);
22672 second_shared_boundary_element_pt.push_back(sele_pt);
22674 second_shared_boundary_element_face_index.push_back(isface);
22682 es = nsecond_element;
22701 template<
class ELEMENT>
22703 std::set<FiniteElement*>& element_in_processor_pt,
22708 const unsigned nproc = this->communicator_pt()->nproc();
22710 const unsigned my_rank = this->communicator_pt()->my_rank();
22720 double tt_start_get_edges_from_shd_bnd_face_ele = 0.0;
22721 if (Print_timings_level_load_balance > 2)
22736 std::map<std::pair<Node*, Node*>,
unsigned> elements_edges_on_boundary;
22739 this->get_element_edges_on_boundary(elements_edges_on_boundary);
22742 std::map<std::pair<Node*, Node*>,
bool> overlapped_edge;
22752 for (
unsigned iproc = 0; iproc < nproc; iproc++)
22755 if (iproc != my_rank)
22759 const unsigned n_shared_bound_ele =
22760 new_shared_boundary_element_pt[iproc].size();
22767 unsigned nrepeated_faces = 0;
22771 for (
unsigned iele = 0; iele < n_shared_bound_ele; iele++)
22775 new_shared_boundary_element_pt[iproc][iele];
22778 int face_index =
static_cast<int>(
22779 new_shared_boundary_element_face_index[iproc][iele]);
22787 bool done_face =
false;
22791 const unsigned nnode_face_ele = tmp_ele_pt->
nnode();
22792 Node* first_face_node_pt = tmp_ele_pt->
node_pt(0);
22793 Node* last_face_node_pt = tmp_ele_pt->
node_pt(nnode_face_ele - 1);
22796 const unsigned ndone_faces = done_faces.size();
22798 for (
unsigned n = 0; n < ndone_faces; n++)
22800 Node* first_done_face_node_pt = done_faces[n].first;
22801 Node* second_done_face_node_pt = done_faces[n].second;
22802 if (first_face_node_pt == first_done_face_node_pt &&
22803 last_face_node_pt == second_done_face_node_pt)
22810 else if (first_face_node_pt == second_done_face_node_pt &&
22811 last_face_node_pt == first_done_face_node_pt)
22824 tmp_unsorted_face_ele_pt[iproc].push_back(tmp_ele_pt);
22826 tmp_unsorted_ele_pt[iproc].push_back(bulk_ele_pt);
22828 tmp_unsorted_face_index_ele[iproc].push_back(face_index);
22830 std::pair<Node*, Node*> tmp_edge =
22831 std::make_pair(first_face_node_pt, last_face_node_pt);
22833 done_faces.push_back(tmp_edge);
22837 int edge_boundary_id = -1;
22838 std::map<std::pair<Node*, Node*>,
unsigned>::iterator it;
22839 it = elements_edges_on_boundary.find(tmp_edge);
22842 if (it != elements_edges_on_boundary.end())
22846 edge_boundary_id = (*it).second;
22848 overlapped_edge[tmp_edge] =
true;
22850 std::pair<Node*, Node*> rev_tmp_edge =
22851 std::make_pair(last_face_node_pt, first_face_node_pt);
22853 overlapped_edge[rev_tmp_edge] =
true;
22858 std::pair<Node*, Node*> rtmp_edge =
22859 std::make_pair(last_face_node_pt, first_face_node_pt);
22860 it = elements_edges_on_boundary.find(rtmp_edge);
22861 if (it != elements_edges_on_boundary.end())
22865 edge_boundary_id = (*it).second;
22867 overlapped_edge[rtmp_edge] =
true;
22870 overlapped_edge[tmp_edge] =
true;
22874 tmp_edge_boundary[iproc].push_back(edge_boundary_id);
22890 if (Print_timings_level_load_balance > 2)
22892 oomph_info <<
"CPU for getting edges from shared boundary face elements "
22893 "(load balance) [9.1]: "
22895 tt_start_get_edges_from_shd_bnd_face_ele
22916 double tt_start_sort_shared_face_elements = 0.0;
22917 if (Print_timings_level_load_balance > 2)
22943 std::vector<std::vector<bool>> tmp_treat_as_inverted(nproc);
22946 std::vector<std::vector<bool>> treat_as_inverted(nproc);
22952 for (
unsigned iproc = 0; iproc < nproc; iproc++)
22955 if (iproc != my_rank)
22958 const unsigned n_face_ele = tmp_unsorted_face_ele_pt[iproc].size();
22965 tmp_treat_as_inverted[iproc].resize(n_face_ele);
22969 for (
unsigned e = 0;
e < n_face_ele;
e++)
22972 FiniteElement* face_ele_pt = tmp_unsorted_face_ele_pt[iproc][
e];
22974 const unsigned n_node = face_ele_pt->
nnode();
22978 Node* node_pt = face_ele_pt->
node_pt(0);
22979 bottom_left[0] = node_pt->x(0);
22980 bottom_left[1] = node_pt->x(1);
22982 tmp_treat_as_inverted[iproc][
e] =
false;
22985 for (
unsigned n = 1; n < n_node; n++)
22988 Node* node_pt = face_ele_pt->
node_pt(n);
22989 if (node_pt->x(1) < bottom_left[1])
22991 bottom_left[0] = node_pt->x(0);
22992 bottom_left[1] = node_pt->x(1);
22995 tmp_treat_as_inverted[iproc][
e] =
true;
22997 else if (node_pt->x(1) == bottom_left[1])
22999 if (node_pt->x(0) < bottom_left[0])
23001 bottom_left[0] = node_pt->x(0);
23002 bottom_left[1] = node_pt->x(1);
23005 tmp_treat_as_inverted[iproc][
e] =
true;
23012 centroid_vertices[
e].resize(2);
23014 centroid_vertices[
e][0] = (face_ele_pt->
node_pt(0)->x(0) +
23015 face_ele_pt->
node_pt(n_node - 1)->x(0)) *
23017 centroid_vertices[
e][1] = (face_ele_pt->
node_pt(0)->x(1) +
23018 face_ele_pt->
node_pt(n_node - 1)->x(1)) *
23024 unsigned n_sorted_bottom_left = 0;
23026 std::vector<bool> done_face(n_face_ele,
false);
23029 while (n_sorted_bottom_left < n_face_ele)
23032 unsigned index = 0;
23034 for (
unsigned e = 0;
e < n_face_ele;
e++)
23040 current_bottom_left[0] = centroid_vertices[
e][0];
23041 current_bottom_left[1] = centroid_vertices[
e][1];
23051 for (
unsigned e = index + 1;
e < n_face_ele;
e++)
23056 if (centroid_vertices[
e][1] < current_bottom_left[1])
23059 current_bottom_left[0] = centroid_vertices[
e][0];
23060 current_bottom_left[1] = centroid_vertices[
e][1];
23064 else if (centroid_vertices[
e][1] == current_bottom_left[1])
23066 if (centroid_vertices[
e][0] < current_bottom_left[0])
23069 current_bottom_left[0] = centroid_vertices[
e][0];
23070 current_bottom_left[1] = centroid_vertices[
e][1];
23082 unsorted_face_ele_pt[iproc].push_back(
23083 tmp_unsorted_face_ele_pt[iproc][index]);
23085 unsorted_ele_pt[iproc].push_back(tmp_unsorted_ele_pt[iproc][index]);
23087 unsorted_face_index_ele[iproc].push_back(
23088 tmp_unsorted_face_index_ele[iproc][index]);
23090 edge_boundary[iproc].push_back(tmp_edge_boundary[iproc][index]);
23092 treat_as_inverted[iproc].push_back(
23093 tmp_treat_as_inverted[iproc][index]);
23096 done_face[index] =
true;
23099 n_sorted_bottom_left++;
23106 const unsigned tmp_n_face_ele = unsorted_face_ele_pt[iproc].size();
23108 if (tmp_n_face_ele != n_face_ele)
23110 std::ostringstream error_stream;
23112 <<
"The number of face elements before sorting them starting\n"
23113 <<
"from their bottom-left vertex is different from the number\n"
23114 <<
"of face elements after the sorting\n"
23115 <<
"N. ele before sorting: (" << n_face_ele <<
")\n"
23116 <<
"N. ele after sorting: (" << tmp_n_face_ele <<
")\n";
23118 error_stream.str(),
23119 "RefineableTriangleMesh::create_new_shared_boundaries()",
23120 OOMPH_EXCEPTION_LOCATION);
23129 if (Print_timings_level_load_balance > 2)
23131 oomph_info <<
"CPU for sorting shared boundary face elements (load "
23155 double tt_start_compute_valency_of_nodes = 0.0;
23156 if (Print_timings_level_load_balance > 2)
23162 std::map<Node*, unsigned> global_node_degree;
23165 compute_shared_node_degree_helper(unsorted_face_ele_pt, global_node_degree);
23168 if (Print_timings_level_load_balance > 2)
23171 <<
"CPU for computing the valency of nodes (load balance) [9.3]: "
23190 double tt_start_nodes_on_non_overlapped_shd_bnd = 0.0;
23191 if (Print_timings_level_load_balance > 2)
23198 std::map<unsigned, std::map<Node*, bool>>
23199 node_on_bnd_not_overlapped_by_shd_bnd;
23202 for (std::map<std::pair<Node*, Node*>,
unsigned>::iterator it_map =
23203 elements_edges_on_boundary.begin();
23204 it_map != elements_edges_on_boundary.end();
23208 std::pair<Node*, Node*> edge_pair = (*it_map).first;
23210 if (!overlapped_edge[edge_pair])
23214 unsigned b = (*it_map).second;
23217 Node* left_node_pt = edge_pair.first;
23218 node_on_bnd_not_overlapped_by_shd_bnd[b][left_node_pt] =
true;
23221 Node* right_node_pt = edge_pair.second;
23222 node_on_bnd_not_overlapped_by_shd_bnd[b][right_node_pt] =
true;
23230 if (Print_timings_level_load_balance > 2)
23232 oomph_info <<
"CPU for computing nodes on non overlapped shared "
23233 "boundaries (load balance) [9.4]: "
23235 tt_start_nodes_on_non_overlapped_shd_bnd
23258 double tt_start_join_shd_bnd_face_ele = 0.0;
23259 if (Print_timings_level_load_balance > 2)
23291 std::map<unsigned, std::list<Node*>>
23292 local_shd_bnd_id_to_sorted_list_node_pt;
23297 unsigned local_shd_bnd_id = this->Initial_shared_boundary_id;
23302 std::map<FiniteElement*, bool> done_ele;
23305 std::map<FiniteElement*, bool> is_inverted;
23309 for (
unsigned iproc = 0; iproc < nproc; iproc++)
23312 if (iproc != my_rank)
23316 const unsigned nunsorted_face_ele = unsorted_face_ele_pt[iproc].size();
23318 unsigned nsorted_face_ele = 0;
23321 while (nsorted_face_ele < nunsorted_face_ele)
23330 bool found_root_element =
false;
23334 unsigned root_index = 0;
23337 std::list<FiniteElement*> tmp_sorted_face_ele_pt;
23340 std::list<FiniteElement*> tmp_sorted_ele_pt;
23344 std::list<int> tmp_sorted_face_index_ele;
23349 std::list<Node*> tmp_sorted_nodes_pt;
23351 tmp_sorted_nodes_pt.clear();
23354 Node* initial_node_pt = 0;
23355 Node* final_node_pt = 0;
23359 int root_edge_bound_id = -1;
23363 for (
unsigned e = 0;
e < nunsorted_face_ele;
e++)
23368 if (!done_ele[root_ele_pt])
23372 root_edge_bound_id = edge_boundary[iproc][
e];
23375 tmp_sorted_face_ele_pt.push_back(root_ele_pt);
23377 tmp_sorted_ele_pt.push_back(unsorted_ele_pt[iproc][
e]);
23380 tmp_sorted_face_index_ele.push_back(
23381 unsorted_face_index_ele[iproc][
e]);
23384 const unsigned nnodes = root_ele_pt->
nnode();
23386 if (!treat_as_inverted[iproc][
e])
23388 initial_node_pt = root_ele_pt->
node_pt(0);
23389 final_node_pt = root_ele_pt->
node_pt(nnodes - 1);
23393 initial_node_pt = root_ele_pt->
node_pt(nnodes - 1);
23394 final_node_pt = root_ele_pt->
node_pt(0);
23397 tmp_sorted_nodes_pt.push_back(initial_node_pt);
23398 tmp_sorted_nodes_pt.push_back(final_node_pt);
23401 done_ele[root_ele_pt] =
true;
23403 if (!treat_as_inverted[iproc][
e])
23406 is_inverted[root_ele_pt] =
false;
23411 is_inverted[root_ele_pt] =
true;
23414 nsorted_face_ele++;
23419 found_root_element =
true;
23429 if (!found_root_element)
23431 std::ostringstream error_stream;
23433 <<
"It was not possible the found the root element\n\n";
23435 OOMPH_CURRENT_FUNCTION,
23436 OOMPH_EXCEPTION_LOCATION);
23444 bool new_element_added =
true;
23454 bool element_added_to_the_left =
false;
23455 bool element_added_to_the_right =
false;
23459 bool connection_to_the_left =
false;
23463 bool connection_to_the_right =
false;
23468 bool current_polyline_has_connections_at_both_ends =
false;
23480 int bound_id_connection_to_the_left = -1;
23481 int bound_id_connection_to_the_right = -1;
23485 const unsigned initial_node_degree =
23486 global_node_degree[initial_node_pt];
23490 const bool called_for_load_balance =
true;
23494 bound_id_connection_to_the_left =
23495 this->check_connections_of_polyline_nodes(
23496 element_in_processor_pt,
23497 root_edge_bound_id,
23499 node_on_bnd_not_overlapped_by_shd_bnd,
23500 tmp_sorted_nodes_pt,
23501 local_shd_bnd_id_to_sorted_list_node_pt,
23502 initial_node_degree,
23504 called_for_load_balance);
23508 if (bound_id_connection_to_the_left != -1)
23510 connection_to_the_left =
true;
23515 const unsigned final_node_degree = global_node_degree[final_node_pt];
23518 bound_id_connection_to_the_right =
23519 this->check_connections_of_polyline_nodes(
23520 element_in_processor_pt,
23521 root_edge_bound_id,
23523 node_on_bnd_not_overlapped_by_shd_bnd,
23524 tmp_sorted_nodes_pt,
23525 local_shd_bnd_id_to_sorted_list_node_pt,
23528 called_for_load_balance);
23532 if (bound_id_connection_to_the_right != -1)
23534 connection_to_the_right =
true;
23539 if (connection_to_the_left && connection_to_the_right)
23541 current_polyline_has_connections_at_both_ends =
true;
23550 while (new_element_added && (nsorted_face_ele < nunsorted_face_ele) &&
23551 !current_polyline_has_connections_at_both_ends)
23557 for (
unsigned e = root_index;
e < nunsorted_face_ele;
e++)
23560 new_element_added =
false;
23561 element_added_to_the_left =
false;
23562 element_added_to_the_right =
false;
23567 const int edge_bound_id = edge_boundary[iproc][
e];
23571 if (!done_ele[tmp_ele_pt] &&
23572 (edge_bound_id == root_edge_bound_id))
23575 const unsigned nnodes = tmp_ele_pt->
nnode();
23578 Node* first_node_pt = 0;
23579 Node* last_node_pt = 0;
23580 if (!treat_as_inverted[iproc][
e])
23582 first_node_pt = tmp_ele_pt->
node_pt(0);
23583 last_node_pt = tmp_ele_pt->
node_pt(nnodes - 1);
23587 first_node_pt = tmp_ele_pt->
node_pt(nnodes - 1);
23588 last_node_pt = tmp_ele_pt->
node_pt(0);
23594 Node* new_added_node_pt = 0;
23597 if (initial_node_pt == last_node_pt && !connection_to_the_left)
23600 new_added_node_pt = initial_node_pt = first_node_pt;
23602 tmp_sorted_nodes_pt.push_front(first_node_pt);
23605 tmp_sorted_face_ele_pt.push_front(tmp_ele_pt);
23607 tmp_sorted_ele_pt.push_front(unsorted_ele_pt[iproc][
e]);
23610 tmp_sorted_face_index_ele.push_front(
23611 unsorted_face_index_ele[iproc][
e]);
23612 if (!treat_as_inverted[iproc][
e])
23615 is_inverted[tmp_ele_pt] =
false;
23620 is_inverted[tmp_ele_pt] =
true;
23623 new_element_added =
true;
23626 element_added_to_the_left =
true;
23629 else if (initial_node_pt == first_node_pt &&
23630 !connection_to_the_left)
23633 new_added_node_pt = initial_node_pt = last_node_pt;
23635 tmp_sorted_nodes_pt.push_front(last_node_pt);
23638 tmp_sorted_face_ele_pt.push_front(tmp_ele_pt);
23640 tmp_sorted_ele_pt.push_front(unsorted_ele_pt[iproc][
e]);
23643 tmp_sorted_face_index_ele.push_front(
23644 unsorted_face_index_ele[iproc][
e]);
23645 if (!treat_as_inverted[iproc][
e])
23648 is_inverted[tmp_ele_pt] =
true;
23653 is_inverted[tmp_ele_pt] =
false;
23656 new_element_added =
true;
23659 element_added_to_the_left =
true;
23662 else if (final_node_pt == first_node_pt &&
23663 !connection_to_the_right)
23666 new_added_node_pt = final_node_pt = last_node_pt;
23668 tmp_sorted_nodes_pt.push_back(last_node_pt);
23671 tmp_sorted_face_ele_pt.push_back(tmp_ele_pt);
23673 tmp_sorted_ele_pt.push_back(unsorted_ele_pt[iproc][
e]);
23676 tmp_sorted_face_index_ele.push_back(
23677 unsorted_face_index_ele[iproc][
e]);
23678 if (!treat_as_inverted[iproc][
e])
23681 is_inverted[tmp_ele_pt] =
false;
23686 is_inverted[tmp_ele_pt] =
true;
23689 new_element_added =
true;
23692 element_added_to_the_right =
true;
23695 else if (final_node_pt == last_node_pt &&
23696 !connection_to_the_right)
23699 new_added_node_pt = final_node_pt = first_node_pt;
23701 tmp_sorted_nodes_pt.push_back(first_node_pt);
23704 tmp_sorted_face_ele_pt.push_back(tmp_ele_pt);
23706 tmp_sorted_ele_pt.push_back(unsorted_ele_pt[iproc][
e]);
23709 tmp_sorted_face_index_ele.push_back(
23710 unsorted_face_index_ele[iproc][
e]);
23711 if (!treat_as_inverted[iproc][
e])
23714 is_inverted[tmp_ele_pt] =
true;
23719 is_inverted[tmp_ele_pt] =
false;
23722 new_element_added =
true;
23725 element_added_to_the_right =
true;
23729 if (new_element_added)
23732 done_ele[tmp_ele_pt] =
true;
23734 nsorted_face_ele++;
23738 const unsigned new_added_node_degree =
23739 global_node_degree[new_added_node_pt];
23748 if (element_added_to_the_left && !connection_to_the_left)
23751 bound_id_connection_to_the_left =
23752 this->check_connections_of_polyline_nodes(
23753 element_in_processor_pt,
23754 root_edge_bound_id,
23756 node_on_bnd_not_overlapped_by_shd_bnd,
23757 tmp_sorted_nodes_pt,
23758 local_shd_bnd_id_to_sorted_list_node_pt,
23759 new_added_node_degree,
23761 called_for_load_balance);
23765 if (bound_id_connection_to_the_left != -1)
23767 connection_to_the_left =
true;
23777 if (element_added_to_the_right && !connection_to_the_right)
23780 bound_id_connection_to_the_right =
23781 this->check_connections_of_polyline_nodes(
23782 element_in_processor_pt,
23783 root_edge_bound_id,
23785 node_on_bnd_not_overlapped_by_shd_bnd,
23786 tmp_sorted_nodes_pt,
23787 local_shd_bnd_id_to_sorted_list_node_pt,
23788 new_added_node_degree,
23790 called_for_load_balance);
23794 if (bound_id_connection_to_the_right != -1)
23796 connection_to_the_right =
true;
23805 if (connection_to_the_left && connection_to_the_right)
23807 current_polyline_has_connections_at_both_ends =
true;
23833 for (std::list<FiniteElement*>::iterator it =
23834 tmp_sorted_ele_pt.begin();
23835 it != tmp_sorted_ele_pt.end();
23838 tmp_vector_sorted_ele_pt.push_back((*it));
23845 for (std::list<FiniteElement*>::iterator it =
23846 tmp_sorted_face_ele_pt.begin();
23847 it != tmp_sorted_face_ele_pt.end();
23850 tmp_vector_sorted_face_ele_pt.push_back((*it));
23856 for (std::list<int>::iterator it = tmp_sorted_face_index_ele.begin();
23857 it != tmp_sorted_face_index_ele.end();
23860 tmp_vector_sorted_face_index_ele.push_back((*it));
23875 Vector<int> final_bound_id_connection_to_the_left;
23878 Vector<int> final_bound_id_connection_to_the_right;
23881 this->break_loops_on_shared_polyline_load_balance_helper(
23883 tmp_sorted_nodes_pt,
23884 tmp_vector_sorted_ele_pt,
23885 tmp_vector_sorted_face_ele_pt,
23886 tmp_vector_sorted_face_index_ele,
23887 bound_id_connection_to_the_left,
23888 bound_id_connection_to_the_right,
23889 final_sorted_nodes_pt,
23890 final_boundary_element_pt,
23891 final_boundary_face_element_pt,
23892 final_face_index_element,
23893 final_bound_id_connection_to_the_left,
23894 final_bound_id_connection_to_the_right);
23897 const unsigned n_final_sorted_nodes = final_sorted_nodes_pt.size();
23900 for (
unsigned i = 0;
i < n_final_sorted_nodes;
i++)
23904 local_shd_bnd_id_to_sorted_list_node_pt[local_shd_bnd_id] =
23905 final_sorted_nodes_pt[
i];
23909 proc_local_shared_boundary_id[iproc].push_back(local_shd_bnd_id);
23914 local_shd_bnd_id++;
23917 sorted_ele_pt[iproc].push_back(final_boundary_element_pt[
i]);
23920 sorted_face_ele_pt[iproc].push_back(
23921 final_boundary_face_element_pt[
i]);
23924 sorted_face_index_ele[iproc].push_back(final_face_index_element[
i]);
23927 edge_boundary_id[iproc].push_back(root_edge_bound_id);
23934 bnd_connections_ids[0] = final_bound_id_connection_to_the_left[
i];
23935 bnd_connections_ids[1] = final_bound_id_connection_to_the_right[
i];
23936 sorted_connection_info[iproc].push_back(bnd_connections_ids);
23948 if (Print_timings_level_load_balance > 2)
23950 oomph_info <<
"CPU for joining shared boundary face elements (load "
23980 double tt_start_get_new_shared_boundaries_ids = 0.0;
23981 if (Print_timings_level_load_balance > 2)
23989 for (
unsigned iproc = 0; iproc < nproc; iproc++)
23992 if (iproc != my_rank)
23996 nshared_boundaries_with_processor[iproc] =
23997 sorted_face_ele_pt[iproc].size();
24007 const unsigned root_processor = 0;
24018 MPI_Gather(&nshared_boundaries_with_processor[0],
24023 &flat_unsigned_root_received_data[0],
24031 comm_pt->mpi_comm());
24040 unsigned new_initial_shared_boundary_id = 0;
24041 unsigned new_final_shared_boundary_id = 0;
24044 if (my_rank == root_processor)
24051 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24054 root_nshared_bound_proc_with_proc[iproc].resize(nproc);
24057 for (
unsigned jproc = 0; jproc < nproc; jproc++)
24059 root_nshared_bound_proc_with_proc[iproc][jproc] =
24060 flat_unsigned_root_received_data[(iproc * nproc) + jproc];
24069 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24071 for (
unsigned jproc = 0; jproc < iproc; jproc++)
24073 if (root_nshared_bound_proc_with_proc[iproc][jproc] !=
24074 root_nshared_bound_proc_with_proc[jproc][iproc])
24076 std::ostringstream error_stream;
24078 <<
"ROOT PROCESSOR ERROR\n\n"
24079 <<
"The number of shared boundaries between processor (" << iproc
24080 <<
") and (" << jproc <<
") is not the same:\n"
24081 <<
"Shared boundaries of processor (" << iproc
24082 <<
") with processor (" << jproc <<
"): ("
24083 << root_nshared_bound_proc_with_proc[iproc][jproc] <<
")\n"
24084 <<
"Shared boundaries of processor (" << jproc
24085 <<
") with processor (" << iproc <<
"): ("
24086 << root_nshared_bound_proc_with_proc[jproc][iproc] <<
")\n\n";
24088 OOMPH_CURRENT_FUNCTION,
24089 OOMPH_EXCEPTION_LOCATION);
24108 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24110 start_shared_bound_id_proc_with_proc[iproc].resize(nproc);
24115 unsigned shared_bound_id = this->nboundary();
24118 new_initial_shared_boundary_id = shared_bound_id;
24121 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24123 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
24126 if (root_nshared_bound_proc_with_proc[iproc][jproc] > 0)
24130 start_shared_bound_id_proc_with_proc[iproc][jproc] =
24132 start_shared_bound_id_proc_with_proc[jproc][iproc] =
24137 shared_bound_id += root_nshared_bound_proc_with_proc[iproc][jproc];
24145 new_final_shared_boundary_id = shared_bound_id;
24148 Vector<unsigned> send_start_shared_bound_id_proc_with_proc(nproc * nproc);
24152 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24154 for (
unsigned jproc = 0; jproc < nproc; jproc++)
24158 const unsigned initial_shd_bnd_id =
24159 start_shared_bound_id_proc_with_proc[iproc][jproc];
24160 flat_unsigned_root_send_receive_data.push_back(initial_shd_bnd_id);
24164 const unsigned nshared_bnd_iproc_jproc =
24165 root_nshared_bound_proc_with_proc[iproc][jproc];
24166 flat_unsigned_root_send_receive_data.push_back(
24167 nshared_bnd_iproc_jproc);
24175 flat_unsigned_root_send_receive_data.push_back(
24176 new_initial_shared_boundary_id);
24179 flat_unsigned_root_send_receive_data.push_back(
24180 new_final_shared_boundary_id);
24191 unsigned root_ndata_sent_to_all_proc =
24192 flat_unsigned_root_send_receive_data.size();
24194 MPI_Bcast(&root_ndata_sent_to_all_proc,
24198 comm_pt->mpi_comm());
24201 if (my_rank != root_processor)
24203 flat_unsigned_root_send_receive_data.resize(root_ndata_sent_to_all_proc);
24208 MPI_Bcast(&flat_unsigned_root_send_receive_data[0],
24211 root_ndata_sent_to_all_proc,
24215 comm_pt->mpi_comm());
24227 unsigned iflat_counter = 0;
24229 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24232 initial_shared_bound_id_proc_with_proc[iproc].resize(nproc);
24233 nshared_bound_proc_with_proc[iproc].resize(nproc);
24236 for (
unsigned jproc = 0; jproc < nproc; jproc++)
24240 initial_shared_bound_id_proc_with_proc[iproc][jproc] =
24241 flat_unsigned_root_send_receive_data[iflat_counter++];
24245 nshared_bound_proc_with_proc[iproc][jproc] =
24246 flat_unsigned_root_send_receive_data[iflat_counter++];
24253 new_initial_shared_boundary_id =
24254 flat_unsigned_root_send_receive_data[root_ndata_sent_to_all_proc - 2];
24257 new_final_shared_boundary_id =
24258 flat_unsigned_root_send_receive_data[root_ndata_sent_to_all_proc - 1];
24261 if (Print_timings_level_load_balance > 2)
24264 <<
"CPU for computing new shared boundaries ids (load balance) [9.6]: "
24286 double tt_start_create_new_shared_boundaries_polylines = 0.0;
24287 if (Print_timings_level_load_balance > 2)
24299 this->flush_shared_boundary_polyline_pt();
24300 this->Shared_boundary_polyline_pt.resize(nproc);
24303 this->Shared_boundaries_ids.clear();
24304 this->Shared_boundaries_ids.resize(nproc);
24305 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24307 this->Shared_boundaries_ids[iproc].clear();
24308 this->Shared_boundaries_ids[iproc].resize(nproc);
24312 this->Shared_boundary_from_processors.clear();
24313 this->Shared_boundary_overlaps_internal_boundary.clear();
24314 this->Boundary_was_splitted.clear();
24315 this->Boundary_subpolylines.clear();
24316 this->Boundary_marked_as_shared_boundary.clear();
24319 this->flush_shared_boundary_element();
24320 this->flush_face_index_at_shared_boundary();
24321 this->flush_shared_boundary_node();
24322 this->flush_sorted_shared_boundary_node();
24326 const unsigned old_local_shd_bnd_id = this->Initial_shared_boundary_id;
24329 this->Initial_shared_boundary_id = new_initial_shared_boundary_id;
24330 this->Final_shared_boundary_id = new_final_shared_boundary_id;
24340 std::map<unsigned, unsigned> local_to_global_shd_bnd_id;
24347 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24353 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
24358 if (iproc == my_rank || jproc == my_rank)
24361 unsigned ref_proc = 0;
24362 if (iproc == my_rank)
24366 else if (jproc == my_rank)
24373 const unsigned nshared_bound_iproc_jproc =
24374 nshared_bound_proc_with_proc[iproc][jproc];
24377 for (
unsigned counter = 0; counter < nshared_bound_iproc_jproc;
24381 const unsigned shd_bnd_id =
24382 initial_shared_bound_id_proc_with_proc[iproc][jproc] + counter;
24385 this->Shared_boundaries_ids[iproc][jproc].push_back(shd_bnd_id);
24386 this->Shared_boundaries_ids[jproc][iproc].push_back(shd_bnd_id);
24391 processors[0] = iproc;
24392 processors[1] = jproc;
24393 this->Shared_boundary_from_processors[shd_bnd_id] = processors;
24398 int root_edge_bound_id = edge_boundary_id[ref_proc][counter];
24401 if (root_edge_bound_id != -1)
24405 this->Shared_boundary_overlaps_internal_boundary[shd_bnd_id] =
24406 static_cast<unsigned>(root_edge_bound_id);
24419 sorted_face_ele_pt[ref_proc][counter][0];
24422 const unsigned first_face_ele_nnodes = first_face_ele_pt->
nnode();
24423 if (!is_inverted[first_face_ele_pt])
24426 Node* first_node_pt = first_face_ele_pt->
node_pt(0);
24428 node_pt_to_create_shared_polyline.push_back(first_node_pt);
24430 this->add_shared_boundary_node(shd_bnd_id, first_node_pt);
24435 Node* first_node_pt =
24436 first_face_ele_pt->
node_pt(first_face_ele_nnodes - 1);
24438 node_pt_to_create_shared_polyline.push_back(first_node_pt);
24440 this->add_shared_boundary_node(shd_bnd_id, first_node_pt);
24448 const unsigned nshared_boundary_elements =
24449 sorted_face_ele_pt[ref_proc][counter].size();
24453 for (
unsigned ie = 0; ie < nshared_boundary_elements; ie++)
24456 FiniteElement* bulk_ele_pt = sorted_ele_pt[ref_proc][counter][ie];
24460 this->add_shared_boundary_element(shd_bnd_id, bulk_ele_pt);
24464 const int face_index =
24465 sorted_face_index_ele[ref_proc][counter][ie];
24469 this->add_face_index_at_shared_boundary(shd_bnd_id, face_index);
24473 sorted_face_ele_pt[ref_proc][counter][ie];
24476 const unsigned nnodes = face_ele_pt->
nnode();
24477 if (!is_inverted[face_ele_pt])
24481 for (
unsigned n = 1; n < nnodes; n++)
24484 Node* node_pt = face_ele_pt->
node_pt(n);
24486 this->add_shared_boundary_node(shd_bnd_id, node_pt);
24492 Node* last_node_pt = face_ele_pt->
node_pt(nnodes - 1);
24493 node_pt_to_create_shared_polyline.push_back(last_node_pt);
24499 for (
int n = nnodes - 2; n >= 0; n--)
24502 Node* node_pt = face_ele_pt->
node_pt(n);
24504 this->add_shared_boundary_node(shd_bnd_id, node_pt);
24510 Node* last_node_pt = face_ele_pt->
node_pt(0);
24511 node_pt_to_create_shared_polyline.push_back(last_node_pt);
24518 const unsigned nnodes_to_create_shared_boundary =
24519 node_pt_to_create_shared_polyline.size();
24523 for (
unsigned n = 0; n < nnodes_to_create_shared_boundary; n++)
24525 vertices[n].resize(2);
24527 Node* tmp_node_pt = node_pt_to_create_shared_polyline[n];
24529 vertices[n][0] = tmp_node_pt->x(0);
24530 vertices[n][1] = tmp_node_pt->x(1);
24538 this->Boundary_curve_section_pt[shd_bnd_id] = polyline_pt;
24542 unsorted_polylines_pt.push_back(polyline_pt);
24545 this->Free_curve_section_pt.insert(polyline_pt);
24551 const unsigned local_shd_bnd_id =
24552 proc_local_shared_boundary_id[ref_proc][counter];
24556 local_to_global_shd_bnd_id[local_shd_bnd_id] = shd_bnd_id;
24563 int tmp_bnd_id_connection_to_the_left =
24564 sorted_connection_info[ref_proc][counter][0];
24566 int tmp_bnd_id_connection_to_the_right =
24567 sorted_connection_info[ref_proc][counter][1];
24571 int bnd_id_connection_to_the_left = -1;
24572 int bnd_id_connection_to_the_right = -1;
24579 if (tmp_bnd_id_connection_to_the_left == -2)
24582 bnd_id_connection_to_the_left = shd_bnd_id;
24586 if (tmp_bnd_id_connection_to_the_left == -3)
24589 bnd_id_connection_to_the_left = -1;
24594 if (tmp_bnd_id_connection_to_the_left >=
24595 static_cast<int>(old_local_shd_bnd_id))
24600 std::map<unsigned, unsigned>::iterator it =
24601 local_to_global_shd_bnd_id.find(
24602 static_cast<unsigned>(tmp_bnd_id_connection_to_the_left));
24605 if (it == local_to_global_shd_bnd_id.end())
24607 std::stringstream error_message;
24609 <<
"The global shared boundary id was not found for\n"
24610 <<
"the local shared boundary shared with processor ("
24611 << ref_proc <<
").\n"
24612 <<
"This processor: (" << my_rank <<
")\n"
24613 <<
"Boundary shared with processor: (" << ref_proc <<
")\n"
24614 <<
"Local shared boundary: ("
24615 << tmp_bnd_id_connection_to_the_left <<
")\n";
24617 OOMPH_CURRENT_FUNCTION,
24618 OOMPH_EXCEPTION_LOCATION);
24623 bnd_id_connection_to_the_left =
24624 local_to_global_shd_bnd_id[
static_cast<unsigned>(
24625 tmp_bnd_id_connection_to_the_left)];
24631 bnd_id_connection_to_the_left = tmp_bnd_id_connection_to_the_left;
24640 if (tmp_bnd_id_connection_to_the_right == -2)
24643 bnd_id_connection_to_the_right = shd_bnd_id;
24647 if (tmp_bnd_id_connection_to_the_right == -3)
24650 bnd_id_connection_to_the_right = -1;
24655 if (tmp_bnd_id_connection_to_the_right >=
24656 static_cast<int>(old_local_shd_bnd_id))
24661 std::map<unsigned, unsigned>::iterator it =
24662 local_to_global_shd_bnd_id.find(
24663 static_cast<unsigned>(tmp_bnd_id_connection_to_the_right));
24666 if (it == local_to_global_shd_bnd_id.end())
24668 std::stringstream error_message;
24670 <<
"The global shared boundary id was not found for\n"
24671 <<
"the local shared boundary shared with processor ("
24672 << ref_proc <<
").\n"
24673 <<
"This processor: (" << my_rank <<
")\n"
24674 <<
"Boundary shared with processor: (" << ref_proc <<
")\n"
24675 <<
"Local shared boundary: ("
24676 << tmp_bnd_id_connection_to_the_right <<
")\n";
24678 OOMPH_CURRENT_FUNCTION,
24679 OOMPH_EXCEPTION_LOCATION);
24683 bnd_id_connection_to_the_right =
24684 local_to_global_shd_bnd_id[
static_cast<unsigned>(
24685 tmp_bnd_id_connection_to_the_right)];
24691 bnd_id_connection_to_the_right =
24692 tmp_bnd_id_connection_to_the_right;
24698 if (bnd_id_connection_to_the_left != -1)
24701 const unsigned ubnd_id_connection_to_the_left =
24702 static_cast<unsigned>(bnd_id_connection_to_the_left);
24707 ubnd_id_connection_to_the_left;
24715 if (bnd_id_connection_to_the_right != -1)
24719 const unsigned ubnd_id_connection_to_the_right =
24720 static_cast<unsigned>(bnd_id_connection_to_the_right);
24725 ubnd_id_connection_to_the_right;
24741 const unsigned nshared_bound_iproc_jproc =
24742 nshared_bound_proc_with_proc[iproc][jproc];
24744 for (
unsigned counter = 0; counter < nshared_bound_iproc_jproc;
24748 const unsigned shd_bnd_id =
24749 initial_shared_bound_id_proc_with_proc[iproc][jproc] + counter;
24752 this->Shared_boundaries_ids[iproc][jproc].push_back(shd_bnd_id);
24753 this->Shared_boundaries_ids[jproc][iproc].push_back(shd_bnd_id);
24758 processors[0] = iproc;
24759 processors[1] = jproc;
24760 this->Shared_boundary_from_processors[shd_bnd_id] = processors;
24771 if (Print_timings_level_load_balance > 2)
24773 oomph_info <<
"CPU for creating new shared boundaries representations "
24774 "(load balance) [9.7]: "
24776 tt_start_create_new_shared_boundaries_polylines
24794 double tt_start_create_new_shared_curves = 0.0;
24795 if (Print_timings_level_load_balance > 2)
24802 if (unsorted_polylines_pt.size() > 0)
24806 this->sort_polylines_helper(unsorted_polylines_pt,
24807 this->Shared_boundary_polyline_pt[my_rank]);
24811 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24813 const unsigned nface_ele = unsorted_face_ele_pt[iproc].size();
24814 for (
unsigned e = 0;
e < nface_ele;
e++)
24816 delete unsorted_face_ele_pt[iproc][
e];
24817 unsorted_face_ele_pt[iproc][
e] = 0;
24823 if (Print_timings_level_load_balance > 2)
24826 <<
"CPU for creating the new shared curves (load balance) [9.8]: "
24844 template<
class ELEMENT>
24847 std::map<Node*, unsigned>& global_node_degree)
24850 const unsigned nproc = this->communicator_pt()->nproc();
24851 const unsigned my_rank = this->communicator_pt()->my_rank();
24862 std::map<Node*, Vector<Vector<unsigned>>> node_alias;
24870 create_adjacency_matrix_new_shared_edges_helper(unsorted_face_ele_pt,
24871 tmp_sorted_shared_node_pt,
24873 local_adjacency_matrix);
24886 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24889 package_unsigned_send_data_to_root.push_back(iproc);
24892 const unsigned n_nodes = tmp_sorted_shared_node_pt[iproc].size();
24895 package_unsigned_send_data_to_root.push_back(n_nodes);
24898 for (
unsigned ishd = 0; ishd < n_nodes; ishd++)
24901 Node* shd_node_pt = tmp_sorted_shared_node_pt[iproc][ishd];
24907 const unsigned n_alias = alias_node_info.size();
24910 package_unsigned_send_data_to_root.push_back(n_alias);
24913 for (
unsigned i = 0;
i < n_alias;
i++)
24917 package_unsigned_send_data_to_root.push_back(alias_node_info[
i][0]);
24919 package_unsigned_send_data_to_root.push_back(alias_node_info[
i][1]);
24921 package_unsigned_send_data_to_root.push_back(alias_node_info[
i][2]);
24927 for (
unsigned i = 0;
i < n_nodes;
i++)
24929 for (
unsigned j = 0; j < n_nodes; j++)
24932 package_unsigned_send_data_to_root.push_back(
24933 local_adjacency_matrix[iproc][
i][j]);
24942 const unsigned root_processor = 0;
24948 unsigned n_unsigned_data_send_to_root =
24949 package_unsigned_send_data_to_root.size();
24952 Vector<int> n_unsigned_data_received_in_root(nproc, 0);
24956 MPI_Gather(&n_unsigned_data_send_to_root,
24960 &n_unsigned_data_received_in_root[0],
24968 comm_pt->mpi_comm());
24971 unsigned n_unsigned_total_data_receive_in_root = 0;
24972 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24975 n_unsigned_total_data_receive_in_root +=
24976 n_unsigned_data_received_in_root[iproc];
24980 Vector<int> root_unsigned_offsets_receive(nproc, 0);
24981 root_unsigned_offsets_receive[0] = 0;
24982 for (
unsigned iproc = 1; iproc < nproc; iproc++)
24986 root_unsigned_offsets_receive[iproc] =
24987 root_unsigned_offsets_receive[iproc - 1] +
24988 n_unsigned_data_received_in_root[iproc - 1];
24992 if (package_unsigned_send_data_to_root.size() == 0)
24994 package_unsigned_send_data_to_root.resize(1);
24999 n_unsigned_total_data_receive_in_root);
25000 if (my_rank != root_processor)
25003 if (package_unsigned_data_received_root.size() == 0)
25005 package_unsigned_data_received_root.resize(1);
25010 MPI_Gatherv(&package_unsigned_send_data_to_root[0],
25015 n_unsigned_data_send_to_root,
25019 &package_unsigned_data_received_root[0],
25025 &n_unsigned_data_received_in_root[0],
25028 &root_unsigned_offsets_receive[0],
25035 comm_pt->mpi_comm());
25040 Vector<int> n_unsigned_data_sent_from_root(nproc, 0);
25044 if (my_rank == root_processor)
25048 unsigned decode_counter = 0;
25061 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25063 local_node_alias[iproc].resize(nproc);
25067 local_adjacency_matrix[iproc].resize(nproc);
25069 if (n_unsigned_data_received_in_root[iproc] > 0)
25073 for (
unsigned jproc = 0; jproc < nproc; jproc++)
25076 const unsigned read_jproc =
25077 package_unsigned_data_received_root[decode_counter++];
25081 if (read_jproc != jproc)
25083 std::ostringstream error_stream;
25085 <<
"The read processor is different from the jproc, this is\n"
25086 <<
"a synchronisation issue. The data are not read in the\n"
25087 <<
"sameorder as the were packaged\n"
25088 <<
"Read processor: (" << read_jproc <<
")\n"
25089 <<
"Current jproc: (" << jproc <<
")\n\n";
25091 error_stream.str(),
25092 "RefineableTriangleMesh::compute_shared_node_degree_helper()",
25093 OOMPH_EXCEPTION_LOCATION);
25098 const unsigned read_n_shd_nodes_iproc_jproc =
25099 package_unsigned_data_received_root[decode_counter++];
25102 local_node_alias[iproc][jproc].resize(read_n_shd_nodes_iproc_jproc);
25106 for (
unsigned ishd = 0; ishd < read_n_shd_nodes_iproc_jproc; ishd++)
25109 const unsigned read_n_alias_node_iproc_jproc =
25110 package_unsigned_data_received_root[decode_counter++];
25113 local_node_alias[iproc][jproc][ishd].resize(
25114 read_n_alias_node_iproc_jproc);
25116 for (
unsigned ialias = 0; ialias < read_n_alias_node_iproc_jproc;
25121 local_node_alias[iproc][jproc][ishd][ialias].resize(3);
25124 local_node_alias[iproc][jproc][ishd][ialias][0] =
25125 package_unsigned_data_received_root[decode_counter++];
25128 local_node_alias[iproc][jproc][ishd][ialias][1] =
25129 package_unsigned_data_received_root[decode_counter++];
25132 local_node_alias[iproc][jproc][ishd][ialias][2] =
25133 package_unsigned_data_received_root[decode_counter++];
25140 local_adjacency_matrix[iproc][jproc].resize(
25141 read_n_shd_nodes_iproc_jproc);
25143 for (
unsigned i = 0;
i < read_n_shd_nodes_iproc_jproc;
i++)
25146 local_adjacency_matrix[iproc][jproc][
i].resize(
25147 read_n_shd_nodes_iproc_jproc);
25148 for (
unsigned j = 0; j < read_n_shd_nodes_iproc_jproc; j++)
25151 local_adjacency_matrix[iproc][jproc][
i][j] =
25152 package_unsigned_data_received_root[decode_counter++];
25164 if (decode_counter != n_unsigned_total_data_receive_in_root)
25166 std::ostringstream error_stream;
25168 <<
"The number of data decoded in root received from others\n"
25169 <<
"processors is different from the total number of data received\n"
25170 <<
"Data decoded: (" << decode_counter <<
")\n"
25171 <<
"Data received: (" << n_unsigned_total_data_receive_in_root
25173 <<
"This is a synchronisation issue so you are probably sending\n"
25174 <<
"more or less info. than the one that is being decoded\n\n";
25176 error_stream.str(),
25177 "RefineableTriangleMesh::compute_shared_node_degree_helper()",
25178 OOMPH_EXCEPTION_LOCATION);
25188 std::map<Vector<unsigned>,
bool> alias_done;
25194 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25196 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
25199 const unsigned n_shd_nodes_iproc_jproc =
25200 local_node_alias[iproc][jproc].size();
25203 const unsigned n_shd_nodes_jproc_iproc =
25204 local_node_alias[jproc][iproc].size();
25206 if (n_shd_nodes_iproc_jproc != n_shd_nodes_jproc_iproc)
25208 std::ostringstream error_stream;
25210 <<
"The number of nodes shared between iproc and jproc is\n"
25211 <<
"different from the number of nodes shared between jproc\n"
25213 <<
"Nodes shared between processor (" << iproc <<
") and "
25214 <<
"processor (" << jproc <<
"): (" << n_shd_nodes_iproc_jproc
25216 <<
"Nodes shared between processor (" << jproc <<
") and "
25217 <<
"processor (" << iproc <<
"): (" << n_shd_nodes_jproc_iproc
25220 error_stream.str(),
25221 "RefineableTriangleMesh::compute_shared_node_degree_helper()",
25222 OOMPH_EXCEPTION_LOCATION);
25227 for (
unsigned ishd = 0; ishd < n_shd_nodes_iproc_jproc; ishd++)
25231 const unsigned n_alias_iproc_jproc =
25232 local_node_alias[iproc][jproc][ishd].size();
25233 const unsigned n_alias_jproc_iproc =
25234 local_node_alias[jproc][iproc][ishd].size();
25240 bool new_alias_added =
false;
25243 for (
unsigned ialias = 0; ialias < n_alias_iproc_jproc; ialias++)
25247 local_node_alias[iproc][jproc][ishd][ialias];
25249 if (!alias_done[current_alias])
25252 node_alias.push_back(current_alias);
25254 new_alias_added =
true;
25256 alias_done[current_alias] =
true;
25262 for (
unsigned ialias = 0; ialias < n_alias_jproc_iproc; ialias++)
25266 local_node_alias[jproc][iproc][ishd][ialias];
25269 if (!alias_done[current_alias])
25272 node_alias.push_back(current_alias);
25274 new_alias_added =
true;
25276 alias_done[current_alias] =
true;
25281 unsigned counter_alias = 0;
25285 unsigned n_current_alias = node_alias.size();
25286 while (new_alias_added || counter_alias < n_current_alias)
25290 new_alias_added =
false;
25296 local_node_alias[current_alias[0]][current_alias[1]]
25297 [current_alias[2]];
25301 const unsigned n_alias = alias_of_current_alias.size();
25305 for (
unsigned k = 0; k < n_alias; k++)
25311 if (!alias_done[add_alias])
25314 node_alias.push_back(add_alias);
25317 new_alias_added =
true;
25319 alias_done[add_alias] =
true;
25327 local_node_alias[current_alias[1]][current_alias[0]]
25328 [current_alias[2]];
25332 const unsigned n_alias2 = alias_of_current_alias2.size();
25336 for (
unsigned k = 0; k < n_alias2; k++)
25342 if (!alias_done[add_alias])
25345 node_alias.push_back(add_alias);
25348 new_alias_added =
true;
25350 alias_done[add_alias] =
true;
25361 n_current_alias = node_alias.size();
25367 if (node_alias.size() > 0)
25371 global_node_alias.push_back(node_alias);
25384 const unsigned n_global_shared_nodes = global_node_alias.size();
25390 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25393 local_to_global_shared_node[iproc].resize(nproc);
25398 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25401 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
25404 const unsigned n_shd_nodes = local_node_alias[iproc][jproc].size();
25407 local_to_global_shared_node[iproc][jproc].resize(n_shd_nodes, -1);
25410 local_to_global_shared_node[jproc][iproc].resize(n_shd_nodes, -1);
25420 for (
unsigned k = 0; k < n_global_shared_nodes; k++)
25423 const unsigned n_alias_global_node = global_node_alias[k].size();
25425 for (
unsigned l = 0; l < n_alias_global_node; l++)
25428 const unsigned iproc = global_node_alias[k][l][0];
25430 const unsigned jproc = global_node_alias[k][l][1];
25432 const unsigned ishd = global_node_alias[k][l][2];
25434 local_to_global_shared_node[iproc][jproc][ishd] = k;
25443 for (
unsigned k = 0; k < n_global_shared_nodes; k++)
25446 global_adjacency_matrix[k].resize(n_global_shared_nodes, 0);
25456 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25459 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
25462 const unsigned n_shd_nodes = local_node_alias[iproc][jproc].size();
25469 for (
unsigned ishd = 0; ishd < n_shd_nodes; ishd++)
25471 for (
unsigned jshd = ishd + 1; jshd < n_shd_nodes; jshd++)
25474 if (local_adjacency_matrix[iproc][jproc][ishd][jshd] > 0)
25479 const int global_shd_node_left =
25480 local_to_global_shared_node[iproc][jproc][ishd];
25483 const int global_shd_node_right =
25484 local_to_global_shared_node[iproc][jproc][jshd];
25489 if (global_shd_node_left == -1)
25491 std::ostringstream error_stream;
25493 <<
"The local node in processors iproc and jproc has no\n"
25494 <<
"global node assigned\n"
25495 <<
"iproc processor: (" << iproc <<
")\n"
25496 <<
"jproc processor: (" << jproc <<
")\n"
25497 <<
"Local node: (" << ishd <<
")\n\n";
25499 "RefineableTriangleMesh::compute_shared_"
25500 "node_degree_helper()",
25501 OOMPH_EXCEPTION_LOCATION);
25506 if (global_shd_node_right == -1)
25508 std::ostringstream error_stream;
25510 <<
"The local node in processors iproc and jproc has no\n"
25511 <<
"global node assigned\n"
25512 <<
"iproc processor: (" << iproc <<
")\n"
25513 <<
"jproc processor: (" << jproc <<
")\n"
25514 <<
"Local node: (" << jshd <<
")\n\n";
25516 "RefineableTriangleMesh::compute_shared_"
25517 "node_degree_helper()",
25518 OOMPH_EXCEPTION_LOCATION);
25522 const unsigned uleft =
25523 static_cast<unsigned>(global_shd_node_left);
25524 const unsigned uright =
25525 static_cast<unsigned>(global_shd_node_right);
25528 global_adjacency_matrix[uleft][uright]++;
25531 global_adjacency_matrix[uright][uleft]++;
25534 global_node_degree[uleft]++;
25537 global_node_degree[uright]++;
25553 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25555 root_local_node_degree[iproc].resize(nproc);
25559 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25562 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
25566 const unsigned n_shd_nodes = local_node_alias[iproc][jproc].size();
25569 root_local_node_degree[iproc][jproc].resize(n_shd_nodes);
25571 root_local_node_degree[jproc][iproc].resize(n_shd_nodes);
25575 for (
unsigned ishd = 0; ishd < n_shd_nodes; ishd++)
25578 const int global_shd_node_id =
25579 local_to_global_shared_node[iproc][jproc][ishd];
25583 if (global_shd_node_id == -1)
25585 std::ostringstream error_stream;
25587 <<
"The local node in processors iproc and jproc has no\n"
25588 <<
"global node assigned\n"
25589 <<
"iproc processor: (" << iproc <<
")\n"
25590 <<
"jproc processor: (" << jproc <<
")\n"
25591 <<
"Local node: (" << ishd <<
")\n\n";
25593 error_stream.str(),
25594 "RefineableTriangleMesh::compute_shared_node_degree_helper()",
25595 OOMPH_EXCEPTION_LOCATION);
25600 const unsigned uglobal_shd_node_id =
25601 static_cast<unsigned>(global_shd_node_id);
25604 const unsigned node_degree =
25605 global_node_degree[uglobal_shd_node_id];
25609 root_local_node_degree[iproc][jproc][ishd] = node_degree;
25611 root_local_node_degree[jproc][iproc][ishd] = node_degree;
25621 package_unsigned_data_sent_from_root.clear();
25625 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25628 unsigned count_n_data_sent_to_iproc = 0;
25629 for (
unsigned jproc = 0; jproc < nproc; jproc++)
25632 if (iproc != jproc)
25635 const unsigned n_shd_nodes =
25636 root_local_node_degree[iproc][jproc].size();
25639 count_n_data_sent_to_iproc += n_shd_nodes;
25642 for (
unsigned ishd = 0; ishd < n_shd_nodes; ishd++)
25644 package_unsigned_data_sent_from_root.push_back(
25645 root_local_node_degree[iproc][jproc][ishd]);
25653 n_unsigned_data_sent_from_root[iproc] = count_n_data_sent_to_iproc;
25660 int n_unsigned_data_received_from_root = 0;
25663 MPI_Scatter(&n_unsigned_data_sent_from_root[0],
25669 &n_unsigned_data_received_from_root,
25676 comm_pt->mpi_comm());
25680 n_unsigned_data_received_from_root);
25683 Vector<int> root_unsigned_offsets_sent(nproc, 0);
25684 root_unsigned_offsets_sent[0] = 0;
25685 for (
unsigned iproc = 1; iproc < nproc; iproc++)
25688 root_unsigned_offsets_sent[iproc] =
25689 root_unsigned_offsets_sent[iproc - 1] +
25690 n_unsigned_data_sent_from_root[iproc - 1];
25693 if (my_rank != root_processor)
25696 if (package_unsigned_data_sent_from_root.size() == 0)
25698 package_unsigned_data_sent_from_root.resize(1);
25703 if (package_unsigned_data_received_from_root.size() == 0)
25705 package_unsigned_data_received_from_root.resize(1);
25709 MPI_Scatterv(&package_unsigned_data_sent_from_root[0],
25714 &n_unsigned_data_sent_from_root[0],
25718 &root_unsigned_offsets_sent[0],
25721 &package_unsigned_data_received_from_root[0],
25729 n_unsigned_data_received_from_root,
25737 comm_pt->mpi_comm());
25742 std::map<Node*, bool> node_done;
25746 int decode_counter = 0;
25750 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25753 if (iproc != my_rank)
25756 const unsigned n_nodes = tmp_sorted_shared_node_pt[iproc].size();
25759 package_unsigned_send_data_to_root.push_back(n_nodes);
25762 for (
unsigned ishd = 0; ishd < n_nodes; ishd++)
25766 const unsigned node_degree =
25767 package_unsigned_data_received_from_root[decode_counter++];
25770 Node* shd_node_pt = tmp_sorted_shared_node_pt[iproc][ishd];
25773 if (!node_done[shd_node_pt])
25776 global_node_degree[shd_node_pt] = node_degree;
25778 node_done[shd_node_pt] =
true;
25785 if (global_node_degree[shd_node_pt] != node_degree)
25787 std::ostringstream error_stream;
25789 <<
"The local node has already assigned a global degree,\n"
25790 <<
"however, a different degree for the same node has been\n"
25791 <<
"read from the data sent from root processor\n"
25792 <<
"iproc processor: (" << iproc <<
")\n"
25793 <<
"Local node: (" << ishd <<
")\n"
25794 <<
"---------------------------------------------------------\n"
25795 <<
"Already assigned degree: ("
25796 << global_node_degree[shd_node_pt] <<
")\n"
25797 <<
"New found degree: (" << node_degree <<
")\n"
25798 <<
"---------------------------------------------------------\n"
25799 <<
"Node coordinates: (" << shd_node_pt->x(0) <<
", "
25800 << shd_node_pt->x(1) <<
")\n\n";
25802 error_stream.str(),
25803 "RefineableTriangleMesh::compute_shared_node_degree_helper()",
25804 OOMPH_EXCEPTION_LOCATION);
25818 if (decode_counter != n_unsigned_data_received_from_root)
25820 std::ostringstream error_stream;
25822 <<
"The number of data decoded received from root processor is\n"
25823 <<
"different from the total number of data received from the root\n"
25825 <<
"Data decoded: (" << decode_counter <<
")\n"
25826 <<
"Data received: (" << n_unsigned_data_received_from_root <<
")\n\n"
25827 <<
"This is a synchronisation issue so you are probably sending\n"
25828 <<
"more or less info. than the one that is being decoded\n\n";
25830 error_stream.str(),
25831 "RefineableTriangleMesh::compute_shared_node_degree_helper()",
25832 OOMPH_EXCEPTION_LOCATION);
25843 template<
class ELEMENT>
25852 const unsigned nproc = this->communicator_pt()->nproc();
25853 const unsigned my_rank = this->communicator_pt()->my_rank();
25862 node_alias.clear();
25868 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25871 if (iproc != my_rank)
25874 std::map<Node*, bool> done_node;
25879 std::map<std::pair<double, double>, Node*,
classcomp> sorted_nodes_pt;
25882 const unsigned n_unsorted_face_ele = unsorted_face_ele_pt[iproc].size();
25885 for (
unsigned e = 0;
e < n_unsorted_face_ele;
e++)
25890 Node* left_node_pt = face_ele_pt->
node_pt(0);
25895 if (!done_node[left_node_pt])
25897 std::pair<double, double> vertex =
25898 std::make_pair(left_node_pt->x(0), left_node_pt->x(1));
25899 sorted_nodes_pt[vertex] = left_node_pt;
25901 done_node[left_node_pt] =
true;
25905 const unsigned n_nodes = face_ele_pt->
nnode();
25907 Node* right_node_pt = face_ele_pt->
node_pt(n_nodes - 1);
25912 if (!done_node[right_node_pt])
25914 std::pair<double, double> vertex =
25915 std::make_pair(right_node_pt->x(0), right_node_pt->x(1));
25916 sorted_nodes_pt[vertex] = right_node_pt;
25918 done_node[right_node_pt] =
true;
25927 unsigned counter = 0;
25931 for (std::map<std::pair<double, double>, Node*>::iterator it =
25932 sorted_nodes_pt.begin();
25933 it != sorted_nodes_pt.end();
25937 Node* node_pt = (*it).second;
25939 tmp_sorted_shared_node_pt[iproc].push_back(node_pt);
25942 tmp_node_index[iproc][node_pt] = counter;
25947 alias[0] = my_rank;
25951 alias[2] = counter++;
25954 node_alias[node_pt].push_back(alias);
25964 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25967 const unsigned n_shd_nodes = tmp_sorted_shared_node_pt[iproc].size();
25969 adjacency_matrix[iproc].resize(n_shd_nodes);
25970 for (
unsigned i = 0;
i < n_shd_nodes;
i++)
25973 adjacency_matrix[iproc][
i].resize(n_shd_nodes);
25976 for (
unsigned j = 0; j < n_shd_nodes; j++)
25978 adjacency_matrix[iproc][
i][j] = 0;
25986 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25989 if (iproc != my_rank)
25992 const unsigned n_unsorted_face_ele = unsorted_face_ele_pt[iproc].size();
25995 for (
unsigned e = 0;
e < n_unsorted_face_ele;
e++)
26000 Node* left_node_pt = face_ele_pt->
node_pt(0);
26003 const unsigned n_nodes = face_ele_pt->
nnode();
26005 Node* right_node_pt = face_ele_pt->
node_pt(n_nodes - 1);
26008 const unsigned left_node_index = tmp_node_index[iproc][left_node_pt];
26009 const unsigned right_node_index =
26010 tmp_node_index[iproc][right_node_pt];
26014 adjacency_matrix[iproc][left_node_index][right_node_index]++;
26016 adjacency_matrix[iproc][right_node_index][left_node_index]++;
26029 template<
class ELEMENT>
26035 tmp_segment_nodes.clear();
26049 const unsigned nshared_bound_ele =
26050 this->nshared_boundary_element(shd_bnd_id);
26054 for (
unsigned e = 0;
e < nshared_bound_ele;
e++)
26058 this->shared_boundary_element_pt(shd_bnd_id,
e);
26061 int face_index = this->face_index_at_shared_boundary(shd_bnd_id,
e);
26072 nonhalo_shared_face_ele_pt.push_back(face_ele_pt);
26078 halo_shared_face_ele_pt.push_back(face_ele_pt);
26085 std::map<FiniteElement*, bool> shared_face_done;
26088 const unsigned nnonhalo_face_shared_ele = nonhalo_shared_face_ele_pt.size();
26094 const unsigned nhalo_face_shared_ele = halo_shared_face_ele_pt.size();
26098 if (nshared_bound_ele / 2 != nnonhalo_face_shared_ele)
26100 std::ostringstream error_message;
26102 <<
"The number of shared boundary elements (" << nshared_bound_ele
26103 <<
") is not the double\nof the number of unsorted nonhalo shared "
26104 <<
"face boundary elements (" << nnonhalo_face_shared_ele
26105 <<
")\n for the current boundary (" << shd_bnd_id <<
")\n\n";
26107 error_message.str(),
26108 "RefineableTriangleMesh::get_shared_boundary_segment_nodes_helper()",
26109 OOMPH_EXCEPTION_LOCATION);
26114 if (nshared_bound_ele / 2 != nhalo_face_shared_ele)
26116 std::ostringstream error_message;
26118 <<
"The number of shared boundary elements (" << nshared_bound_ele
26119 <<
") is not the double\nof the number of unsorted halo shared "
26120 <<
"face boundary elements (" << nhalo_face_shared_ele
26121 <<
")\n for the current boundary (" << shd_bnd_id <<
")\n\n";
26123 error_message.str(),
26124 "RefineableTriangleMesh::get_shared_boundary_segment_nodes_helper()",
26125 OOMPH_EXCEPTION_LOCATION);
26131 for (
unsigned inh = 0; inh < nnonhalo_face_shared_ele; inh++)
26134 FiniteElement* nonhalo_face_ele_pt = nonhalo_shared_face_ele_pt[inh];
26137 const unsigned nnodes_nh = nonhalo_face_ele_pt->
nnode();
26139 Node* nh_first_node_pt = nonhalo_face_ele_pt->
node_pt(0);
26140 Node* nh_last_node_pt = nonhalo_face_ele_pt->
node_pt(nnodes_nh - 1);
26144 for (
unsigned ih = 0; ih < nhalo_face_shared_ele; ih++)
26147 FiniteElement* halo_face_ele_pt = halo_shared_face_ele_pt[ih];
26150 if (!shared_face_done[halo_face_ele_pt])
26153 const unsigned nnodes_h = halo_face_ele_pt->
nnode();
26155 Node* h_first_node_pt = halo_face_ele_pt->
node_pt(0);
26156 Node* h_last_node_pt = halo_face_ele_pt->
node_pt(nnodes_h - 1);
26160 if (nh_first_node_pt == h_first_node_pt &&
26161 nh_last_node_pt == h_last_node_pt)
26164 shared_face_done[nonhalo_face_ele_pt] =
true;
26165 shared_face_done[halo_face_ele_pt] =
true;
26171 else if (nh_first_node_pt == h_last_node_pt &&
26172 nh_last_node_pt == h_first_node_pt)
26175 shared_face_done[nonhalo_face_ele_pt] =
true;
26176 shared_face_done[halo_face_ele_pt] =
true;
26191 if ((nnonhalo_face_shared_ele + nhalo_face_shared_ele) !=
26192 shared_face_done.size())
26194 std::ostringstream error_message;
26195 error_message <<
"The number of DONE shared boundary face elements ("
26196 << shared_face_done.size()
26197 <<
") is not the same\n as the sum of"
26198 <<
"the nonhalo face shared boundary elements ("
26199 << nnonhalo_face_shared_ele
26200 <<
")\nand the halo face shared "
26201 <<
"boundary elements (" << nhalo_face_shared_ele
26203 <<
"current boundary (" << shd_bnd_id <<
")\n\n";
26205 error_message.str(),
26206 "RefineableTriangleMesh::get_shared_boundary_segment_nodes_helper()",
26207 OOMPH_EXCEPTION_LOCATION);
26219 shared_face_done.clear();
26221 unsigned nsorted_face_ele = 0;
26224 std::list<Node*> sorted_nodes;
26227 FiniteElement* root_face_ele_pt = nonhalo_shared_face_ele_pt[0];
26228 nsorted_face_ele++;
26231 shared_face_done[root_face_ele_pt] =
true;
26234 const unsigned nnodes_root = root_face_ele_pt->
nnode();
26235 Node* first_node_pt = root_face_ele_pt->
node_pt(0);
26236 Node* last_node_pt = root_face_ele_pt->
node_pt(nnodes_root - 1);
26239 sorted_nodes.push_back(first_node_pt);
26240 sorted_nodes.push_back(last_node_pt);
26243 while (nsorted_face_ele < nnonhalo_face_shared_ele)
26246 bool node_added =
false;
26250 for (
unsigned iface = 1; iface < nnonhalo_face_shared_ele; iface++)
26253 nonhalo_shared_face_ele_pt[iface];
26256 if (!shared_face_done[tmp_shared_face_ele_pt])
26259 const unsigned tmp_nnodes = tmp_shared_face_ele_pt->
nnode();
26262 Node* left_node_pt = tmp_shared_face_ele_pt->
node_pt(0);
26263 Node* right_node_pt = tmp_shared_face_ele_pt->
node_pt(tmp_nnodes - 1);
26265 if (left_node_pt == first_node_pt)
26268 sorted_nodes.push_front(right_node_pt);
26269 first_node_pt = right_node_pt;
26272 else if (left_node_pt == last_node_pt)
26275 sorted_nodes.push_back(right_node_pt);
26276 last_node_pt = right_node_pt;
26279 else if (right_node_pt == first_node_pt)
26282 sorted_nodes.push_front(left_node_pt);
26283 first_node_pt = left_node_pt;
26286 else if (right_node_pt == last_node_pt)
26289 sorted_nodes.push_back(left_node_pt);
26290 last_node_pt = left_node_pt;
26298 shared_face_done[tmp_shared_face_ele_pt] =
true;
26299 nsorted_face_ele++;
26315 for (
unsigned inh = 0; inh < nnonhalo_face_shared_ele; inh++)
26317 delete nonhalo_shared_face_ele_pt[inh];
26318 nonhalo_shared_face_ele_pt[inh] = 0;
26323 for (
unsigned ih = 0; ih < nhalo_face_shared_ele; ih++)
26325 delete halo_shared_face_ele_pt[ih];
26326 halo_shared_face_ele_pt[ih] = 0;
26334 const unsigned n_nodes = sorted_nodes.size();
26337 tmp_segment_nodes.resize(1);
26338 tmp_segment_nodes[0].resize(n_nodes);
26341 unsigned counter = 0;
26344 for (std::list<Node*>::iterator it = sorted_nodes.begin();
26345 it != sorted_nodes.end();
26348 tmp_segment_nodes[0][counter] = (*it);
26359 template<
class ELEMENT>
26367 const unsigned nbound = this->initial_shared_boundary_id();
26370 const unsigned nproc = this->communicator_pt()->nproc();
26378 unsigned counter_face_indexes = 0;
26380 for (
unsigned b = 0; b < nbound; b++)
26383 const unsigned nboundary_ele = nboundary_element(b);
26384 for (
unsigned e = 0;
e < nboundary_ele;
e++)
26386 if (ele_pt == this->boundary_element_pt(b,
e))
26389 associated_boundaries.push_back(b);
26391 face_index_on_boundary.push_back(face_index_at_boundary(b,
e));
26392 counter_face_indexes++;
26394 if (counter_face_indexes > 2)
26396 std::stringstream error_message;
26398 <<
"A triangular element can not have more than two of its faces "
26399 <<
"on a boundary!!!\n\n";
26401 "RefineableTriangleMesh::get_required_"
26402 "elemental_information_helper()",
26403 OOMPH_EXCEPTION_LOCATION);
26407 if (counter_face_indexes == 2)
26421 const unsigned nassociated_boundaries = associated_boundaries.size();
26422 if (nassociated_boundaries > 0)
26425#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26427 "The element is a boundary element");
26430#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26431 std::stringstream junk;
26432 junk <<
"The elements is associated to " << nassociated_boundaries
26441 for (
unsigned i = 0;
i < nassociated_boundaries;
i++)
26443 unsigned b = associated_boundaries[
i];
26445#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26446 std::stringstream junk;
26447 junk <<
"Element associated to boundary " << b <<
" of "
26448 << nassociated_boundaries <<
" total associated boundaries";
26451 unsigned f = face_index_on_boundary[
i];
26453#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26454 std::stringstream junk2;
26455 junk2 <<
"Face index " <<
f <<
" for associated boundary " << b;
26470 const unsigned n_regions = this->nregion();
26475 unsigned counter_face_indexes_in_regions = 0;
26477 for (
unsigned b = 0; b < nbound; b++)
26480 for (
unsigned i_reg = 0; i_reg < n_regions; i_reg++)
26483 const unsigned region_id =
26484 static_cast<unsigned>(this->Region_attribute[i_reg]);
26489 const unsigned nele_in_region =
26490 this->nboundary_element_in_region(b, region_id);
26491 for (
unsigned ee = 0; ee < nele_in_region; ee++)
26496 this->boundary_element_in_region_pt(b, region_id, ee))
26503 bound_and_region[0] = b;
26505 bound_and_region[1] = region_id;
26508 associated_boundaries_and_regions.push_back(bound_and_region);
26510 face_index_on_boundary_and_region.push_back(
26511 this->face_index_at_boundary_in_region(b, region_id, ee));
26515 counter_face_indexes_in_regions++;
26518 if (counter_face_indexes_in_regions > 2)
26520 std::stringstream error_message;
26521 error_message <<
"A triangular element can not have more "
26522 "than two of its\n"
26523 <<
"faces on a boundary!!!\n\n";
26525 "RefineableTriangleMesh::get_required_"
26526 "elemental_information_helper()",
26527 OOMPH_EXCEPTION_LOCATION);
26542 const unsigned nassociated_boundaries_and_regions =
26543 associated_boundaries_and_regions.size();
26544 if (nassociated_boundaries_and_regions > 0)
26547#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26549 "The element is associated to boundaries and regions");
26553#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26554 std::stringstream junk;
26555 junk <<
"The element is associated to "
26556 << nassociated_boundaries_and_regions <<
" boundaries-regions";
26564 for (
unsigned i = 0;
i < nassociated_boundaries_and_regions;
i++)
26566 const unsigned b = associated_boundaries_and_regions[
i][0];
26568#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26569 std::stringstream junk;
26570 junk <<
"Element associated to boundary " << b <<
" of "
26571 << nassociated_boundaries_and_regions
26572 <<
" total associated boundaries-regions";
26576 const unsigned r = associated_boundaries_and_regions[
i][1];
26578#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26579 std::stringstream junk2;
26580 junk2 <<
"Element associated to region " << r <<
" of "
26581 << nassociated_boundaries_and_regions
26582 <<
" total associated boundaries-regions";
26586 const unsigned f = face_index_on_boundary_and_region[
i];
26588#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26589 std::stringstream junk3;
26590 junk3 <<
"Face index " <<
f <<
" for associated boundary-region ("
26591 << b <<
"-" << r <<
")";
26599#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26601 "The element is NOT associated to boundaries and regions");
26608#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26610 "The element is not associated to any original boundary");
26624 this->shared_boundaries_in_this_processor(my_rank_shared_boundaries_ids);
26627 const unsigned nmy_rank_shd_bnd = my_rank_shared_boundaries_ids.size();
26629 for (
unsigned i = 0;
i < nmy_rank_shd_bnd;
i++)
26632 const unsigned sb = my_rank_shared_boundaries_ids[
i];
26635 const unsigned nboundary_ele = this->nshared_boundary_element(sb);
26636 for (
unsigned e = 0;
e < nboundary_ele;
e++)
26638 if (ele_pt == this->shared_boundary_element_pt(sb,
e))
26641 associated_shared_boundaries.push_back(sb);
26643 face_index_on_shared_boundary.push_back(
26644 this->face_index_at_shared_boundary(sb,
e));
26651 const unsigned nassociated_shared_boundaries =
26652 associated_shared_boundaries.size();
26653 if (nassociated_shared_boundaries > 0)
26656#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26658 "The element is a shared boundary element");
26661#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26662 std::stringstream junk;
26663 junk <<
"The elements is associated to " << nassociated_shared_boundaries
26664 <<
"shared boundaries";
26669 for (
unsigned i = 0;
i < nassociated_shared_boundaries;
i++)
26671 const unsigned b = associated_shared_boundaries[
i];
26673#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26674 std::stringstream junk;
26675 junk <<
"Element associated to shared boundary " << b <<
" of "
26676 << nassociated_shared_boundaries <<
" total associated boundaries";
26680 const unsigned f = face_index_on_shared_boundary[
i];
26682#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26683 std::stringstream junk2;
26684 junk2 <<
"Face index " <<
f <<
" for associated shared boundary " << b;
26692#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26694 "The element is not associated to any shared boundary");
26704 for (
unsigned jproc = 0; jproc < nproc; jproc++)
26707 const unsigned n_haloed_jproc = f_haloed_ele_pt[jproc].size();
26709 for (
unsigned ihd = 0; ihd < n_haloed_jproc; ihd++)
26712 if (ele_pt == f_haloed_ele_pt[jproc][ihd])
26715 index_haloed[jproc].push_back(ihd);
26726 for (
unsigned jproc = 0; jproc < nproc; jproc++)
26729 const unsigned n_index_haloed_jproc = index_haloed[jproc].size();
26731#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26733 "The number of haloed indexes the element is with processor jproc");
26735 for (
unsigned ihd = 0; ihd < n_index_haloed_jproc; ihd++)
26738#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26740 "The haloed index of the element with jproc");
26751 template<
class ELEMENT>
26759 const unsigned nnew_nodes_on_domain = new_nodes_on_domain.size();
26760 const unsigned new_added_node_index =
26761 this->try_to_add_node_pt_load_balance(new_nodes_on_domain, nod_pt);
26764 if (new_added_node_index == nnew_nodes_on_domain)
26768#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26769 std::stringstream junk;
26770 junk <<
"Node needs to be constructed [size="
26779 get_required_nodal_information_load_balance_helper(
26780 f_halo_ele_pt, iproc, nod_pt);
26785#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26786 std::stringstream junk;
26788 <<
"]; last entry: "
26797#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26808 template<
class ELEMENT>
26815 unsigned my_rank = this->communicator_pt()->my_rank();
26816 const unsigned nproc = this->communicator_pt()->nproc();
26821 unsigned n_val = nod_pt->nvalue();
26823#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26827 unsigned n_dim = nod_pt->ndim();
26830 unsigned n_prev = 1;
26831 if (this->Time_stepper_pt != 0)
26834 n_prev = this->Time_stepper_pt->ntstorage();
26843 const unsigned n_bnd = this->initial_shared_boundary_id();
26844 for (
unsigned bb = 0; bb < n_bnd; bb++)
26847 if (nod_pt->is_on_boundary(bb))
26849 original_boundaries.push_back(bb);
26853 const unsigned n_original_boundaries = original_boundaries.size();
26855 if (n_original_boundaries > 0)
26859#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26861 "Node is on the original boundaries");
26865#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26866 std::stringstream junk;
26867 junk <<
"Node is on " << n_original_boundaries <<
" original boundaries";
26872 for (
unsigned i = 0;
i < n_original_boundaries;
i++)
26875#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26876 std::stringstream junk;
26877 junk <<
"Node is on boundary " << original_boundaries[
i] <<
" of "
26883 nod_pt->get_coordinates_on_boundary(original_boundaries[
i], zeta);
26891#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26893 "Node is on any original boundary");
26899 bool node_on_shared_boundary =
false;
26902 const unsigned n_shd_bnd = this->nshared_boundaries(my_rank, iproc);
26903 for (
unsigned bb = 0; bb < n_shd_bnd; bb++)
26906 unsigned i_bnd = this->shared_boundaries_ids(my_rank, iproc, bb);
26908 if (this->is_node_on_shared_boundary(i_bnd, nod_pt))
26910 node_on_shared_boundary =
true;
26918 if (node_on_shared_boundary)
26921#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26928 for (
unsigned bb = 0; bb < n_shd_bnd; bb++)
26931 const unsigned i_bnd = this->shared_boundaries_ids(my_rank, iproc, bb);
26933 if (this->is_node_on_shared_boundary(i_bnd, nod_pt))
26935 shd_boundaries.push_back(i_bnd);
26940 const unsigned n_shd_bnd_is_on = shd_boundaries.size();
26943#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26944 std::stringstream junk;
26945 junk <<
"Node is on " << n_shd_bnd_is_on <<
" shared boundaries";
26950 for (
unsigned i = 0;
i < n_shd_bnd_is_on;
i++)
26953#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26954 std::stringstream junk;
26955 junk <<
"Node is on boundary " << shd_boundaries[
i] <<
" of " << nb;
26962 unsigned shared_boundary_id = shd_boundaries[0];
26964 const unsigned n_nodes_on_shared_boundary =
26965 nsorted_shared_boundary_node(shared_boundary_id);
26967 unsigned index_node_on_shared_boundary;
26970 bool found_index_node_on_shared_boundary =
false;
26973 for (
unsigned i = 0;
i < n_nodes_on_shared_boundary;
i++)
26976 Node* shared_node_pt =
26977 sorted_shared_boundary_node_pt(shared_boundary_id,
i);
26979 if (shared_node_pt == nod_pt)
26982 index_node_on_shared_boundary =
i;
26985 found_index_node_on_shared_boundary =
true;
26993 if (!found_index_node_on_shared_boundary)
26995 std::ostringstream error_message;
26996 error_message <<
"The index of the node on boundary ("
26997 << shared_boundary_id <<
") was not found.\n"
26998 <<
"The node coordinates are (" << nod_pt->x(0) <<
","
26999 << nod_pt->x(1) <<
").\n";
27001 error_message.str(),
27002 "RefineableTriangleMesh::get_required_nodal_information_helper()",
27003 OOMPH_EXCEPTION_LOCATION);
27008#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27009 std::stringstream junk2;
27010 junk2 <<
"Node index on boundary " << boundaries[0] <<
" is "
27011 << index_node_on_shared_boundary;
27020#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27022 "Node is not on a shared boundary");
27037 bool node_on_shared_boundary_with_other_processors =
false;
27039 unsigned nshared_boundaries_with_other_processors_have_node = 0;
27043 for (
unsigned jproc = 0; jproc < nproc; jproc++)
27047 if (jproc != iproc)
27050 const unsigned n_jshd_bnd = this->nshared_boundaries(my_rank, jproc);
27052 for (
unsigned bb = 0; bb < n_jshd_bnd; bb++)
27055 const unsigned j_shd_bnd =
27056 this->shared_boundaries_ids(my_rank, jproc, bb);
27058 if (this->is_node_on_shared_boundary(j_shd_bnd, nod_pt))
27066 node_on_shared_boundary_with_other_processors =
true;
27069 nshared_boundaries_with_other_processors_have_node++;
27080 if (node_on_shared_boundary_with_other_processors)
27083#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27085 "Node is on shared boundary no related with the received processor: 4");
27092 nshared_boundaries_with_other_processors_have_node);
27093#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27094 std::stringstream junk;
27095 junk <<
"Number of other shared boundaries that the node is on: "
27096 << nshared_boundaries_with_other_processors_have_node;
27101 unsigned counter_shd_bnd_with_other_procs_have_node = 0;
27111 for (
unsigned jproc = 0; jproc < nproc; jproc++)
27115 if (jproc != iproc)
27119 const unsigned n_jshd_bnd = this->nshared_boundaries(my_rank, jproc);
27120 for (
unsigned bb = 0; bb < n_jshd_bnd; bb++)
27123 const unsigned j_shd_bnd =
27124 this->shared_boundaries_ids(my_rank, jproc, bb);
27126 if (this->is_node_on_shared_boundary(j_shd_bnd, nod_pt))
27129 other_processor_1.push_back(my_rank);
27131 other_processor_2.push_back(jproc);
27133 shd_bnd_ids.push_back(j_shd_bnd);
27136 counter_shd_bnd_with_other_procs_have_node++;
27147 const unsigned n_other_processors = other_processor_1.size();
27149 for (
unsigned i = 0;
i < n_other_processors;
i++)
27152 unsigned shd_bnd_id = shd_bnd_ids[
i];
27154 const unsigned n_nodes_on_shd_bnd =
27155 nsorted_shared_boundary_node(shd_bnd_id);
27158 bool found_index_node_on_shared_boundary =
false;
27160 for (
unsigned i = 0;
i < n_nodes_on_shd_bnd;
i++)
27163 Node* shared_node_pt = sorted_shared_boundary_node_pt(shd_bnd_id,
i);
27165 if (shared_node_pt == nod_pt)
27171 indexes.push_back(
i);
27174 found_index_node_on_shared_boundary =
true;
27182 if (!found_index_node_on_shared_boundary)
27184 std::ostringstream error_message;
27185 error_message <<
"The index of the node on boundary (" << shd_bnd_id
27186 <<
"), shared by other processors\nwas not found.\n"
27187 <<
"The node coordinates are (" << nod_pt->x(0) <<
","
27188 << nod_pt->x(1) <<
").\n";
27190 error_message.str(),
27191 "RefineableTriangleMesh::get_required_nodal_information_helper()",
27192 OOMPH_EXCEPTION_LOCATION);
27201 if (counter_shd_bnd_with_other_procs_have_node !=
27202 nshared_boundaries_with_other_processors_have_node)
27204 std::ostringstream error_message;
27205 error_message <<
"The number of shared boundaries where the node is on "
27206 <<
"is different:\n"
27207 <<
"nshared_boundaries_with_other_processors_have_node: ("
27208 << nshared_boundaries_with_other_processors_have_node
27210 <<
"counter_shd_bnd_with_other_procs_have_node: ("
27211 << counter_shd_bnd_with_other_procs_have_node <<
")\n";
27213 error_message.str(),
27214 "RefineableTriangleMesh::get_required_nodal_information_helper()",
27215 OOMPH_EXCEPTION_LOCATION);
27221 for (
unsigned i = 0;
i < n_other_processors;
i++)
27224#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27225 std::stringstream junk1;
27226 junk1 <<
"Processor where the other shared boundary "
27227 <<
"has the node: " << other_processor_1[
i];
27232#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27233 std::stringstream junk2;
27234 junk2 <<
"Processor where the other shared boundary "
27235 <<
"has the node: " << other_processor_2[
i];
27240#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27241 std::stringstream junk3;
27242 junk3 <<
"Other shared boundary id where the node is on"
27248#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27249 std::stringstream junk4;
27250 junk4 <<
"Node index on other shared boundary " << boundaries[
i]
27251 <<
" is " << indexes[
i];
27261#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27263 "Node is on any shared boundary with other processors");
27295 for (
unsigned jproc = 0; jproc < nproc; jproc++)
27298 const unsigned n_halo_jproc = f_halo_ele_pt[jproc].size();
27300 for (
unsigned jh = 0; jh < n_halo_jproc; jh++)
27304 const unsigned n_node = halo_ele_pt->
nnode();
27306 for (
unsigned n = 0; n < n_node; n++)
27309 if (nod_pt == halo_ele_pt->
node_pt(n))
27311 halo_element_number[jproc].push_back(jh);
27312 halo_node_number_in_halo_element[jproc].push_back(n);
27328 for (
unsigned jproc = 0; jproc < nproc; jproc++)
27332 const unsigned n_jproc_halo_ele_node_is_on =
27333 halo_element_number[jproc].size();
27336#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27337 std::stringstream junk5;
27338 junk5 <<
"Node is on " << n_jproc_halo_ele_node_is_on <<
" halo "
27339 <<
"elements with " << jproc <<
"-th processor";
27345 for (
unsigned i = 0;
i < n_jproc_halo_ele_node_is_on;
i++)
27348 const unsigned halo_element_index = halo_element_number[jproc][
i];
27350#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27351 std::stringstream junk6;
27352 junk6 <<
"Halo element index is (" << halo_element_index
27353 <<
") with processor (" << jproc <<
")";
27357 const unsigned node_index = halo_node_number_in_halo_element[jproc][
i];
27359#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27360 std::stringstream junk7;
27361 junk7 <<
"The node index on the halo element index is (" << node_index;
27377 bool on_halo_element_with_iproc_processor =
false;
27378 if (halo_element_number[iproc].size() > 0)
27380 on_halo_element_with_iproc_processor =
true;
27384 if (!node_on_shared_boundary && !on_halo_element_with_iproc_processor)
27392 if (alg_nod_pt != 0)
27400#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27405 unsigned n_ref_val = alg_nod_pt->
nref_value();
27407#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27410 for (
unsigned i_ref_val = 0; i_ref_val < n_ref_val; i_ref_val++)
27418#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27421 for (
unsigned i_geom = 0; i_geom < n_geom_obj; i_geom++)
27429 unsigned found_geom_object = 0;
27430 for (
unsigned i_list = 0; i_list < n_geom_list; i_list++)
27434 found_geom_object = i_list;
27438#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27446 if (solid_nod_pt != 0)
27449 for (
unsigned i_val = 0; i_val < n_solid_val; i_val++)
27451 for (
unsigned t = 0;
t < n_prev;
t++)
27460 const unsigned nvalues_solid_node = values_solid_node.size();
27462#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27463 std::stringstream junk;
27464 junk <<
"Number of values solid node: " << nvalues_solid_node;
27467 for (
unsigned i = 0;
i < nvalues_solid_node;
i++)
27474 for (
unsigned i_val = 0; i_val < n_val; i_val++)
27476 for (
unsigned t = 0;
t < n_prev;
t++)
27483 for (
unsigned idim = 0; idim < n_dim; idim++)
27485 for (
unsigned t = 0;
t < n_prev;
t++)
27500 template<
class ELEMENT>
27505 received_old_haloed_element_pt,
27509 other_proc_shd_bnd_node_pt,
27514#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27516 <<
" Bool: New element needs to be constructed "
27535 new_elements_on_domain.push_back(f_el_pt);
27538 this->add_element_load_balance_helper(
27539 iproc, received_old_haloed_element_pt, f_el_pt);
27542 unsigned n_node = f_el_pt->
nnode();
27543 for (
unsigned j = 0; j < n_node; j++)
27545 Node* new_nod_pt = 0;
27548 add_received_node_load_balance_helper(new_nod_pt,
27550 received_old_haloed_element_pt,
27551 new_nodes_on_domain,
27552 other_proc_shd_bnd_node_pt,
27557 node_name_to_global_index,
27558 global_shared_node_pt);
27563#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27565 <<
" Index of existing element "
27583 template<
class ELEMENT>
27585 const unsigned& iproc,
27587 received_old_haloed_element_pt,
27591 const unsigned nproc = this->communicator_pt()->nproc();
27593#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27595 <<
" Bool: Element is associated to a boundary "
27601 const unsigned is_on_original_boundary =
27603 if (is_on_original_boundary == 1)
27605#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27607 <<
" How many boundaries are associated with the element "
27612 const unsigned nassociated_boundaries =
27616 for (
unsigned b = 0; b < nassociated_boundaries; b++)
27618#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27620 <<
" Boundary associated to the element "
27626 const unsigned bnd =
27629#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27631 <<
" Face index of the element "
27637 const unsigned face_index =
27642 this->Boundary_element_pt[bnd].push_back(ele_pt);
27643 this->Face_index_at_boundary[bnd].push_back(face_index);
27648#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27650 <<
" Bool: Element is associated to a boundary-region "
27658#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27661 <<
" How many boundaries-regions are associated with the element "
27666 const unsigned nassociated_boundaries_and_regions =
27669 for (
unsigned br = 0; br < nassociated_boundaries_and_regions; br++)
27671#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27673 <<
" Boundary associated to the element "
27678 const unsigned bnd =
27681#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27683 <<
" Region associated to the element "
27688 const unsigned region =
27691#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27693 <<
" Face index of the element in boundary-region "
27697 const unsigned face_index =
27702 this->Boundary_region_element_pt[bnd][region].push_back(ele_pt);
27703 this->Face_index_region_at_boundary[bnd][region].push_back(
27714 if (is_on_original_boundary != 0)
27716 std::ostringstream error_message;
27718 <<
"The current element is not on an original boundary, this should\n"
27719 <<
"be indicated by a zero flag. However, the read value for\n"
27720 <<
"that flag is (" << is_on_original_boundary <<
").\n\n";
27722 error_message.str(),
27723 "RefineableTriangleMesh::add_element_load_balance_helper()",
27724 OOMPH_EXCEPTION_LOCATION);
27729#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27731 <<
" Bool: Element is associated to a shared boundary "
27737 const unsigned is_on_shared_boundary =
27739 if (is_on_shared_boundary == 3)
27741#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27744 <<
" How many shared boundaries are associated with the element "
27750 const unsigned nassociated_shared_boundaries =
27754 for (
unsigned b = 0; b < nassociated_shared_boundaries; b++)
27756#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27758 <<
" Shared boundary associated to the element "
27762 const unsigned bnd =
27765#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27768 <<
" Face index of the element associated to the shared boundary "
27773 const unsigned face_index =
27776 this->add_shared_boundary_element(bnd, ele_pt);
27777 this->add_face_index_at_shared_boundary(bnd, face_index);
27785 if (is_on_shared_boundary != 0)
27787 std::ostringstream error_message;
27789 <<
"The current element is not on a shared boundary, this should\n"
27790 <<
"be indicated by a zero flag. However, the read value for\n"
27791 <<
"that flag is (" << is_on_shared_boundary <<
").\n\n";
27793 error_message.str(),
27794 "RefineableTriangleMesh::add_element_load_balance_helper()",
27795 OOMPH_EXCEPTION_LOCATION);
27804 for (
unsigned jproc = 0; jproc < nproc; jproc++)
27806#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27808 <<
" Bool: Number of haloed indexes of the element with the "
27809 << jproc <<
" processor: "
27814 const unsigned n_index_haloed_jproc =
27817 for (
unsigned ihd = 0; ihd < n_index_haloed_jproc; ihd++)
27819#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27821 <<
" Bool: The haloed element index with the " << jproc
27826 const unsigned haloed_index =
27830 received_old_haloed_element_pt[iproc][jproc][haloed_index] = ele_pt;
27840 template<
class ELEMENT>
27845 received_old_haloed_element_pt,
27848 other_proc_shd_bnd_node_pt,
27850 unsigned& node_index,
27858#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27860 <<
" Bool: New node needs to be constructed "
27868 construct_new_node_load_balance_helper(new_nod_pt,
27870 received_old_haloed_element_pt,
27871 new_nodes_on_domain,
27872 other_proc_shd_bnd_node_pt,
27877 node_name_to_global_index,
27878 global_shared_node_pt);
27882#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27884 <<
" Index of existing halo node "
27891 new_nod_pt = new_nodes_on_domain
27895 new_el_pt->
node_pt(node_index) = new_nod_pt;
27904 template<
class ELEMENT>
27909 received_old_haloed_element_pt,
27912 other_proc_shd_bnd_node_pt,
27914 unsigned& node_index,
27921 const unsigned nproc = this->communicator_pt()->nproc();
27923 const unsigned my_rank = this->communicator_pt()->my_rank();
27927#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27929 <<
" Number of values of external halo node "
27936 TimeStepper* time_stepper_pt = this->Time_stepper_pt;
27938 unsigned n_prev = time_stepper_pt->
ntstorage();
27942#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27944 <<
" Is the node on an original boundary "
27950 const unsigned node_on_original_boundaries =
27958 unsigned n_original_boundaries_node_is_on = 0;
27960 if (node_on_original_boundaries == 2)
27963#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27965 <<
" Number of boundaries the node is on: "
27969 n_original_boundaries_node_is_on =
27973 original_boundaries_node_is_on.resize(n_original_boundaries_node_is_on);
27974 zeta_coordinates.resize(n_original_boundaries_node_is_on);
27976 for (
unsigned i = 0;
i < n_original_boundaries_node_is_on;
i++)
27979#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27981 <<
" Node is on boundary "
27985 original_boundaries_node_is_on[
i] =
27987 zeta_coordinates[
i] =
27995 if (node_on_original_boundaries != 0)
27997 std::ostringstream error_message;
27999 <<
"The current node is not on an original boundary, this should\n"
28000 <<
"be indicated by a zero flag. However, the read value for\n"
28001 <<
"that flag is (" << node_on_original_boundaries <<
").\n\n";
28003 error_message.str(),
28004 "RefineableTriangleMesh::construct_new_halo_node_helper()",
28005 OOMPH_EXCEPTION_LOCATION);
28013#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28015 <<
" Is node on shared boundary? "
28019 const unsigned is_node_on_shared_boundary =
28021 if (is_node_on_shared_boundary == 1)
28024#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28026 <<
" Number of boundaries the node is on: "
28030 const unsigned n_shd_bnd_node_is_on =
28033 for (
unsigned i = 0;
i < n_shd_bnd_node_is_on;
i++)
28036#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28038 <<
" Node is on boundary "
28042 shd_bnds_node_is_on[
i] =
28047#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28049 <<
" Index of node on boundary "
28054 unsigned node_index_on_shared_boundary =
28058 new_nod_pt = this->sorted_shared_boundary_node_pt(
28059 shd_bnds_node_is_on[0], node_index_on_shared_boundary);
28065 if (is_node_on_shared_boundary != 0)
28067 std::ostringstream error_message;
28069 <<
"The current node is not on a shared boundary, this should\n"
28070 <<
"be indicated by a zero flag. However, the read value for\n"
28071 <<
"that flag is (" << is_node_on_shared_boundary <<
").\n\n";
28073 error_message.str(),
28074 "RefineableTriangleMesh::construct_new_halo_node_helper()",
28075 OOMPH_EXCEPTION_LOCATION);
28082#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28084 <<
" Is the node on shared boundaries with other processors "
28091 const unsigned is_the_node_in_shared_boundaries_with_other_processors =
28101 unsigned n_shd_bnd_with_other_procs_have_node = 0;
28104 if (is_the_node_in_shared_boundaries_with_other_processors == 4)
28106#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28108 <<
" In how many shared boundaries with other "
28109 <<
"processors is the node "
28115 n_shd_bnd_with_other_procs_have_node =
28119 other_processor_1.resize(n_shd_bnd_with_other_procs_have_node);
28120 other_processor_2.resize(n_shd_bnd_with_other_procs_have_node);
28121 other_shared_boundaries.resize(n_shd_bnd_with_other_procs_have_node);
28122 other_indexes.resize(n_shd_bnd_with_other_procs_have_node);
28124 for (
unsigned i = 0;
i < n_shd_bnd_with_other_procs_have_node;
i++)
28126#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28128 <<
" Processor where the other shared boundary"
28134 other_processor_1[
i] =
28137#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28139 <<
" Processor where the other shared boundary"
28145 other_processor_2[
i] =
28148#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28150 <<
" Other shared boundary id where the node is on: "
28156 other_shared_boundaries[
i] =
28159#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28161 <<
" Node index on the other shared boundary "
28176 if (is_the_node_in_shared_boundaries_with_other_processors != 0)
28178 std::ostringstream error_message;
28180 <<
"The current node is not on a shared boundary with\n"
28181 <<
"other processors, this should be indicated by a zero flag.\n"
28182 <<
"However, the read value for that flag is ("
28183 << is_the_node_in_shared_boundaries_with_other_processors <<
").\n\n";
28185 error_message.str(),
28186 "RefineableTriangleMesh::construct_new_node_load_balance_helper()",
28187 OOMPH_EXCEPTION_LOCATION);
28202 for (
unsigned jproc = 0; jproc < nproc; jproc++)
28204#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28206 <<
" The node is on "
28208 <<
" halo elements with " << jproc <<
" processor"
28213 const unsigned n_jproc_halo_ele_node_is_on =
28217 halo_element_number[jproc].resize(n_jproc_halo_ele_node_is_on);
28218 halo_node_number_in_halo_element[jproc].resize(
28219 n_jproc_halo_ele_node_is_on);
28224 for (
unsigned i = 0;
i < n_jproc_halo_ele_node_is_on;
i++)
28227#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28229 <<
" The halo element index where the node is on "
28234 const unsigned halo_ele_index =
28236#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28238 <<
" The node index on the halo element where the node "
28243 const unsigned node_index_on_halo_ele =
28247 halo_element_number[jproc][
i] = halo_ele_index;
28249 halo_node_number_in_halo_element[jproc][
i] = node_index_on_halo_ele;
28258 std::set<Node*> set_haloed_node_pt;
28261 Node* haloed_node_pt = 0;
28267 bool on_haloed_element_with_iproc_processor =
false;
28268 if (halo_element_number[my_rank].size() > 0)
28272 on_haloed_element_with_iproc_processor =
true;
28275 const unsigned n_haloed_indexes = halo_element_number[my_rank].size();
28279 for (
unsigned i = 0;
i < n_haloed_indexes;
i++)
28282 const unsigned haloed_index = halo_element_number[my_rank][
i];
28284 const unsigned haloed_node_index =
28285 halo_node_number_in_halo_element[my_rank][
i];
28288 FiniteElement* tmp_haloed_ele_pt = f_haloed_ele_pt[iproc][haloed_index];
28290 Node* tmp_haloed_node_pt =
28291 tmp_haloed_ele_pt->
node_pt(haloed_node_index);
28294 haloed_node_pt = tmp_haloed_node_pt;
28297 set_haloed_node_pt.insert(tmp_haloed_node_pt);
28300 if (set_haloed_node_pt.size() > 1)
28302 std::ostringstream error_message;
28304 <<
"When adding the " << haloed_node_index <<
" node of the "
28305 << haloed_index <<
"-th haloed element\n"
28306 <<
"in the currrent processor with the " << iproc <<
" processor"
28307 <<
"it was found that\nthe node pointer is different from the other"
28308 <<
"instances of the node.\nIt means we have a repeated node."
28309 <<
"This are the node coordinates of the previous node instances\n"
28310 <<
"The last entry is for the just added node with a different "
28313 for (std::set<Node*>::iterator it = set_haloed_node_pt.begin();
28314 it != set_haloed_node_pt.end();
28317 error_message <<
"Node: (" << (*it)->x(0) <<
", " << (*it)->x(1)
28320 error_message <<
"\n";
28322 error_message.str(),
28323 "RefineableTriangleMesh::construct_new_node_load_balance_helper()",
28324 OOMPH_EXCEPTION_LOCATION);
28334 bool found_on_haloed_element_with_other_processor =
false;
28337 for (
unsigned jproc = 0; jproc < iproc; jproc++)
28340 if (halo_element_number[jproc].size() > 0)
28343 const unsigned n_halo_indexes = halo_element_number[jproc].size();
28347 for (
unsigned i = 0;
i < n_halo_indexes;
i++)
28350 const unsigned haloed_index = halo_element_number[jproc][
i];
28352 const unsigned haloed_node_index =
28353 halo_node_number_in_halo_element[jproc][
i];
28357 std::map<unsigned, FiniteElement*>::iterator it_map =
28358 received_old_haloed_element_pt[jproc][iproc].find(haloed_index);
28360 if (it_map != received_old_haloed_element_pt[jproc][iproc].end())
28365 found_on_haloed_element_with_other_processor =
true;
28370 Node* tmp_haloed_node_pt =
28371 tmp_haloed_ele_pt->
node_pt(haloed_node_index);
28374 haloed_node_pt = tmp_haloed_node_pt;
28377 set_haloed_node_pt.insert(tmp_haloed_node_pt);
28380 if (set_haloed_node_pt.size() > 1)
28382 std::ostringstream error_message;
28384 <<
"When adding the " << haloed_node_index <<
" node of the "
28385 << haloed_index <<
"-th haloed element "
28386 <<
"of the " << jproc <<
" processor\nwith the " << iproc
28387 <<
" processor, it was found that\n"
28388 <<
"the node pointer is different from the other\n"
28389 <<
"instances of the node.\nThis means we have a repeated "
28391 <<
"These are the node coordinates of the previous node "
28393 <<
"The last entry is for the just added node with a "
28395 <<
"node pointer\n";
28396 for (std::set<Node*>::iterator it = set_haloed_node_pt.begin();
28397 it != set_haloed_node_pt.end();
28400 error_message <<
"Node: (" << (*it)->x(0) <<
", " << (*it)->x(1)
28403 error_message <<
"\n";
28405 "RefineableTriangleMesh::construct_new_node_"
28406 "load_balance_helper()",
28407 OOMPH_EXCEPTION_LOCATION);
28425 if (on_haloed_element_with_iproc_processor ||
28426 found_on_haloed_element_with_other_processor)
28429 new_nod_pt = haloed_node_pt;
28437 if (is_node_on_shared_boundary == 1 ||
28438 (on_haloed_element_with_iproc_processor))
28443 if (node_on_original_boundaries == 2)
28449 for (
unsigned i = 0;
i < n_original_boundaries_node_is_on;
i++)
28451 add_boundary_node(original_boundaries_node_is_on[
i], new_nod_pt);
28454 zeta[0] = zeta_coordinates[
i];
28455 new_nod_pt->set_coordinates_on_boundary(
28456 original_boundaries_node_is_on[
i], zeta);
28462 new_nodes_on_domain.push_back(new_nod_pt);
28465 new_el_pt->
node_pt(node_index) = new_nod_pt;
28475 bool found_node_in_other_shared_boundaries =
false;
28484 bool build_node_as_boundary_node =
false;
28486 if (is_the_node_in_shared_boundaries_with_other_processors == 4)
28489 build_node_as_boundary_node =
true;
28496 const unsigned initial_shd_bnd_id = this->initial_shared_boundary_id();
28503 for (
unsigned i = 0;
i < n_shd_bnd_with_other_procs_have_node;
i++)
28505 unsigned oproc1 = other_processor_1[
i];
28506 unsigned oproc2 = other_processor_2[
i];
28510 if (oproc1 > oproc2)
28513 oproc1 = other_processor_2[
i];
28518 const unsigned shd_bnd_id =
28519 other_shared_boundaries[
i] - initial_shd_bnd_id;
28521 const unsigned index = other_indexes[
i];
28525 const unsigned n_nodes_on_other_processor =
28526 other_proc_shd_bnd_node_pt[oproc1][oproc2][shd_bnd_id].size();
28528 if (n_nodes_on_other_processor > 0)
28532 std::map<unsigned, Node*>::iterator it =
28533 other_proc_shd_bnd_node_pt[oproc1][oproc2][shd_bnd_id].find(index);
28537 other_proc_shd_bnd_node_pt[oproc1][oproc2][shd_bnd_id].end())
28540 found_node_in_other_shared_boundaries =
true;
28542 Node* tmp_node_pt =
28543 other_proc_shd_bnd_node_pt[oproc1][oproc2][shd_bnd_id][index];
28544 found_node_pt.push_back(tmp_node_pt);
28554 if (found_node_in_other_shared_boundaries)
28557 const unsigned ntimes_node_found = found_node_pt.size();
28558 for (
unsigned j = 1; j < ntimes_node_found; j++)
28560 if (found_node_pt[j - 1] != found_node_pt[j])
28562 std::ostringstream error_message;
28564 <<
"The instances of the node that was found to be on a\n"
28565 <<
"shared boundary with other processors are not the same,\n"
28566 <<
"the coordinates for the nodes are these:\n"
28567 <<
"(" << found_node_pt[j - 1]->x(0) <<
", "
28568 << found_node_pt[j - 1]->x(1) <<
")\n"
28569 <<
"(" << found_node_pt[j]->x(0) <<
", " << found_node_pt[j]->x(1)
28571 <<
"Not be surprised if they are the same since the node is\n"
28572 <<
"repeated!!!\n";
28574 error_message.str(),
28575 "RefineableTriangleMesh::construct_new_halo_node_helper()",
28576 OOMPH_EXCEPTION_LOCATION);
28587 if (is_node_on_shared_boundary == 1)
28592 if (found_node_pt[0] != new_nod_pt)
28594 std::ostringstream error_message;
28596 <<
"The pointer of the node that was found to be on a\n"
28597 <<
"shared boundary with other processor(s) and the pointer\n"
28598 <<
"of the node on shared boundary with the receiver\n"
28599 <<
"processor (iproc) are not the same. This means we have a\n"
28600 <<
"repeated node)\n"
28601 <<
"The coordinates for the nodes are:\n"
28602 <<
"(" << found_node_pt[0]->x(0) <<
", " << found_node_pt[0]->x(1)
28604 <<
"(" << new_nod_pt->x(0) <<
", " << new_nod_pt->x(1) <<
")\n"
28605 <<
"Not to be surprised if they are the same since the node is\n"
28606 <<
"repeated!!!\n";
28608 error_message.str(),
28609 "RefineableTriangleMesh::construct_new_halo_node_helper()",
28610 OOMPH_EXCEPTION_LOCATION);
28619 new_nod_pt = found_node_pt[0];
28631 if (is_node_on_shared_boundary != 1 &&
28632 !on_haloed_element_with_iproc_processor)
28646 if (node_on_original_boundaries == 2 || build_node_as_boundary_node)
28652 if (!found_node_in_other_shared_boundaries ||
28653 !found_on_haloed_element_with_other_processor)
28656 if (time_stepper_pt != 0)
28671 new_el_pt->
node_pt(node_index) = new_nod_pt;
28676 for (
unsigned i = 0;
i < n_original_boundaries_node_is_on;
i++)
28678 add_boundary_node(original_boundaries_node_is_on[
i], new_nod_pt);
28681 zeta[0] = zeta_coordinates[
i];
28682 new_nod_pt->set_coordinates_on_boundary(
28683 original_boundaries_node_is_on[
i], zeta);
28693 if (!found_node_in_other_shared_boundaries ||
28694 !found_on_haloed_element_with_other_processor)
28697 if (time_stepper_pt != 0)
28699 new_nod_pt = new_el_pt->
construct_node(node_index, time_stepper_pt);
28710 new_el_pt->
node_pt(node_index) = new_nod_pt;
28722 new_nodes_on_domain.push_back(new_nod_pt);
28728 if (!found_node_in_other_shared_boundaries ||
28729 !found_on_haloed_element_with_other_processor)
28732 this->add_node_pt(new_nod_pt);
28741 if (new_alg_nod_pt != 0)
28750#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28752 <<
" Alg node update id "
28757 unsigned update_id =
28764#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28766 <<
" Alg node # of ref values "
28770 unsigned n_ref_val =
28775 ref_value.resize(n_ref_val);
28776 for (
unsigned i_ref = 0; i_ref < n_ref_val; i_ref++)
28789#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28791 <<
" Alg node # of geom objects "
28795 unsigned n_geom_obj =
28800 geom_object_pt.resize(n_geom_obj);
28801 for (
unsigned i_geom = 0; i_geom < n_geom_obj; i_geom++)
28803#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28805 <<
" Alg node: geom object index "
28809 unsigned geom_index =
28824 if (!found_node_in_other_shared_boundaries ||
28825 !found_on_haloed_element_with_other_processor)
28830 update_id, alg_mesh_pt, geom_object_pt, ref_value);
28844 if (!found_node_in_other_shared_boundaries ||
28845 !found_on_haloed_element_with_other_processor)
28851 if (macro_nod_pt != 0)
28866 s_in_macro_node_update_element);
28870 new_el_pt, s_in_macro_node_update_element, geom_object_vector_pt);
28877 unsigned n_new_val = new_nod_pt->nvalue();
28883 if (!found_node_in_other_shared_boundaries ||
28884 !found_on_haloed_element_with_other_processor)
28886 if (n_val > n_new_val)
28902 new std::map<unsigned, unsigned>;
28906 std::map<unsigned, unsigned>* map_pt =
28911 const unsigned id_face = 0;
28913 std::map<unsigned, unsigned>::const_iterator p =
28914 map_pt->find(id_face);
28917 if (p == map_pt->end())
28921 (*map_pt)[id_face] = n_new_val;
28924 new_nod_pt->resize(n_val);
28934 if (solid_nod_pt != 0)
28937 for (
unsigned i_val = 0; i_val < n_solid_val; i_val++)
28939 for (
unsigned t = 0;
t < n_prev;
t++)
28948 if (!found_node_in_other_shared_boundaries ||
28949 !found_on_haloed_element_with_other_processor)
28952 t, i_val, read_data);
28958#ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28960 <<
" Number of values solid node: "
28964 const unsigned nvalues_solid_node =
28967 for (
unsigned i = 0;
i < nvalues_solid_node;
i++)
28969 values_solid_node[
i] =
28977 if (!found_node_in_other_shared_boundaries ||
28978 !found_on_haloed_element_with_other_processor)
28980 unsigned index = 0;
28988 for (
unsigned i_val = 0; i_val < n_val; i_val++)
28990 for (
unsigned t = 0;
t < n_prev;
t++)
28999 if (!found_node_in_other_shared_boundaries ||
29000 !found_on_haloed_element_with_other_processor)
29002 new_nod_pt->set_value(
t, i_val, read_data);
29009 unsigned n_dim = new_nod_pt->ndim();
29010 for (
unsigned idim = 0; idim < n_dim; idim++)
29012 for (
unsigned t = 0;
t < n_prev;
t++)
29021 if (!found_node_in_other_shared_boundaries ||
29022 !found_on_haloed_element_with_other_processor)
29025 new_nod_pt->x(
t, idim) = read_data;
29038 if (n_shd_bnd_with_other_procs_have_node > 0 &&
29042 !found_node_in_other_shared_boundaries)
29050 this->update_other_proc_shd_bnd_node_helper(new_nod_pt,
29051 other_proc_shd_bnd_node_pt,
29054 other_shared_boundaries,
29057 node_name_to_global_index,
29058 global_shared_node_pt);
29071 template<
class ELEMENT>
29076 tmp_segment_nodes.clear();
29086 unsigned n_repeated_ele = 0;
29089 const unsigned n_regions = this->nregion();
29097 for (
unsigned rr = 0; rr < n_regions; rr++)
29099 const unsigned region_id =
29100 static_cast<unsigned>(this->Region_attribute[rr]);
29103 const unsigned nel_in_region =
29104 this->nboundary_element_in_region(b, region_id);
29107 unsigned nel_repeated_in_region = 0;
29111 if (nel_in_region > 0)
29115 bool repeated =
false;
29118 for (
unsigned e = 0;
e < nel_in_region;
e++)
29122 this->boundary_element_in_region_pt(b, region_id,
e);
29124#ifdef OOMPH_HAS_MPI
29126 if (this->is_mesh_distributed() && bulk_elem_pt->
is_halo())
29137 this->face_index_at_boundary_in_region(b, region_id,
e);
29146 const unsigned n_nodes = tmp_ele_pt->
nnode();
29148 std::pair<Node*, Node*> tmp_pair = std::make_pair(
29151 std::pair<Node*, Node*> tmp_pair_inverse = std::make_pair(
29155 unsigned n_done_nodes = done_nodes_pt.size();
29156 for (
unsigned l = 0; l < n_done_nodes; l++)
29158 if (tmp_pair == done_nodes_pt[l] ||
29159 tmp_pair_inverse == done_nodes_pt[l])
29161 nel_repeated_in_region++;
29172 done_nodes_pt.push_back(tmp_pair);
29174 face_el_pt.push_back(tmp_ele_pt);
29190 nel += nel_in_region;
29193 n_repeated_ele += nel_repeated_in_region;
29204 nel = this->nboundary_element(b);
29211 bool repeated =
false;
29214 for (
unsigned e = 0;
e < nel;
e++)
29219#ifdef OOMPH_HAS_MPI
29221 if (this->is_mesh_distributed() && bulk_elem_pt->
is_halo())
29231 int face_index = this->face_index_at_boundary(b,
e);
29239 const unsigned n_nodes = tmp_ele_pt->
nnode();
29241 std::pair<Node*, Node*> tmp_pair = std::make_pair(
29244 std::pair<Node*, Node*> tmp_pair_inverse = std::make_pair(
29248 unsigned n_done_nodes = done_nodes_pt.size();
29249 for (
unsigned l = 0; l < n_done_nodes; l++)
29251 if (tmp_pair == done_nodes_pt[l] ||
29252 tmp_pair_inverse == done_nodes_pt[l])
29265 done_nodes_pt.push_back(tmp_pair);
29267 face_el_pt.push_back(tmp_ele_pt);
29286 nel -= n_repeated_ele;
29289 if (nel != face_el_pt.size())
29291 std::ostringstream error_message;
29293 <<
"The independet counting of face elements (" << nel <<
") for "
29294 <<
"boundary (" << b <<
") is different\n"
29295 <<
"from the real number of face elements in the container ("
29296 << face_el_pt.size() <<
")\n";
29298 error_message.str(),
29299 "RefineableTriangleMesh::get_boundary_segment_nodes_helper()",
29300 OOMPH_EXCEPTION_LOCATION);
29308 const unsigned nnon_halo_face_elements = nel;
29316 unsigned nsorted_face_elements = 0;
29320 std::map<FiniteElement*, bool> done_ele;
29325 std::map<FiniteElement*, bool> is_inverted;
29330 while (nsorted_face_elements < nnon_halo_face_elements)
29334 std::list<FiniteElement*> sorted_el_pt;
29338 bool found_initial_face_element =
false;
29343 unsigned iface = 0;
29344#ifdef OOMPH_HAS_MPI
29345 if (this->is_mesh_distributed())
29347 for (iface = 0; iface < nel; iface++)
29349 ele_face_pt = face_el_pt[iface];
29351 if (!done_ele[ele_face_pt])
29356 found_initial_face_element =
true;
29359 nsorted_face_elements++;
29363 sorted_el_pt.push_back(ele_face_pt);
29365 done_ele[ele_face_pt] =
true;
29376 ele_face_pt = face_el_pt[0];
29379 found_initial_face_element =
true;
29382 nsorted_face_elements++;
29386 sorted_el_pt.push_back(ele_face_pt);
29388 done_ele[ele_face_pt] =
true;
29389#ifdef OOMPH_HAS_MPI
29394 if (!found_initial_face_element)
29396 std::ostringstream error_message;
29397 error_message <<
"Could not find an initial face element for the "
29398 "current segment\n";
29400 error_message.str(),
29401 "RefineableTriangleMesh::get_boundary_segment_nodes_helper()",
29402 OOMPH_EXCEPTION_LOCATION);
29407 const unsigned nnod = ele_face_pt->
nnode();
29411 Node* left_node_pt = ele_face_pt->
node_pt(0);
29412 Node* right_node_pt = ele_face_pt->
node_pt(nnod - 1);
29416 bool face_element_added =
false;
29426 for (
unsigned iiface = iface; iiface < nel; iiface++)
29429 face_element_added =
false;
29432 ele_face_pt = face_el_pt[iiface];
29436 if (!done_ele[ele_face_pt])
29439 Node* local_left_node_pt = ele_face_pt->node_pt(0);
29440 Node* local_right_node_pt = ele_face_pt->node_pt(nnod - 1);
29443 if (left_node_pt == local_right_node_pt)
29445 left_node_pt = local_left_node_pt;
29446 sorted_el_pt.push_front(ele_face_pt);
29447 is_inverted[ele_face_pt] =
false;
29448 face_element_added =
true;
29451 else if (left_node_pt == local_left_node_pt)
29453 left_node_pt = local_right_node_pt;
29454 sorted_el_pt.push_front(ele_face_pt);
29455 is_inverted[ele_face_pt] =
true;
29456 face_element_added =
true;
29459 else if (right_node_pt == local_left_node_pt)
29461 right_node_pt = local_right_node_pt;
29462 sorted_el_pt.push_back(ele_face_pt);
29463 is_inverted[ele_face_pt] =
false;
29464 face_element_added =
true;
29467 else if (right_node_pt == local_right_node_pt)
29469 right_node_pt = local_left_node_pt;
29470 sorted_el_pt.push_back(ele_face_pt);
29471 is_inverted[ele_face_pt] =
true;
29472 face_element_added =
true;
29475 if (face_element_added)
29478 done_ele[ele_face_pt] =
true;
29479 nsorted_face_elements++;
29487 }
while (face_element_added &&
29488 (nsorted_face_elements < nnon_halo_face_elements));
29491 segment_sorted_ele_pt.push_back(sorted_el_pt);
29496 const unsigned nsegments = segment_sorted_ele_pt.size();
29499 if (nnon_halo_face_elements > 0 && nsegments == 0)
29501 std::ostringstream error_message;
29503 <<
"The number of segments is zero, but the number of nonhalo\n"
29504 <<
"elements is: (" << nnon_halo_face_elements <<
")\n";
29506 error_message.str(),
29507 "RefineableTriangleMesh::get_boundary_segment_nodes_helper()",
29508 OOMPH_EXCEPTION_LOCATION);
29517 tmp_segment_nodes.resize(nsegments);
29519 for (
unsigned is = 0; is < nsegments; is++)
29522 if (segment_sorted_ele_pt[is].size() == 0)
29524 std::ostringstream error_message;
29525 error_message <<
"The (" << is <<
")-th segment has no elements\n";
29527 error_message.str(),
29528 "RefineableTriangleMesh::get_boundary_segment_nodes_helper()",
29529 OOMPH_EXCEPTION_LOCATION);
29534 FiniteElement* first_ele_pt = segment_sorted_ele_pt[is].front();
29537 const unsigned nnod = first_ele_pt->
nnode();
29540 Node* first_node_pt = first_ele_pt->
node_pt(0);
29541 if (is_inverted[first_ele_pt])
29543 first_node_pt = first_ele_pt->
node_pt(nnod - 1);
29547 tmp_segment_nodes[is].push_back(first_node_pt);
29550 for (std::list<FiniteElement*>::iterator it =
29551 segment_sorted_ele_pt[is].begin();
29552 it != segment_sorted_ele_pt[is].end();
29559 Node* last_node_pt = 0;
29562 if (!is_inverted[ele_pt])
29564 last_node_pt = ele_pt->
node_pt(nnod - 1);
29568 last_node_pt = ele_pt->
node_pt(0);
29572 tmp_segment_nodes[is].push_back(last_node_pt);
29581 for (
unsigned e = 0;
e < nel;
e++)
29583 delete face_el_pt[
e];
29594 template<
class ELEMENT>
29605 double min_angle = compute_area_target(elem_error, target_area);
29610 bool quantised_areas =
true;
29611 if (quantised_areas)
29613 unsigned n = target_area.size();
29614 double total_area = 0;
29620#ifdef OOMPH_HAS_MPI
29621 if (this->is_mesh_distributed())
29625 double sub_area = 0.0;
29628 for (
unsigned e = 0;
e < n;
e++)
29634 sub_area += ele_pt->
size();
29643 &sub_area, &total_area, 1, MPI_DOUBLE, MPI_SUM, comm_pt->mpi_comm());
29647 for (
unsigned e = 0;
e < n;
e++)
29649 total_area += this->finite_element_pt(
e)->size();
29656 for (
unsigned e = 0;
e < n;
e++)
29658 total_area += this->finite_element_pt(
e)->size();
29662 for (
unsigned e = 0;
e < n;
e++)
29665 unsigned(ceil(log(target_area[
e] / total_area) / log(1.0 / 3.0))) - 1;
29666 double new_target_area = total_area * pow(1.0 / 3.0,
int(level));
29667 target_area[
e] = new_target_area;
29677 unsigned n = target_area.size();
29678 double max_area = 0.0;
29679 double min_area = DBL_MAX;
29680 for (
unsigned e = 0;
e < n;
e++)
29682 if (target_area[
e] > max_area) max_area = target_area[
e];
29683 if (target_area[
e] < min_area) min_area = target_area[
e];
29698 oomph_info <<
"Maximum target area: " << max_area << std::endl;
29699 oomph_info <<
"Minimum target area: " << min_area << std::endl;
29700 oomph_info <<
"Number of elements to be refined: " << this->Nrefined
29702 oomph_info <<
"Number of elements to be unrefined: " << this->Nunrefined
29704 oomph_info <<
"Min. angle: " << min_angle << std::endl;
29706 double orig_max_area, orig_min_area;
29707 this->max_and_min_element_size(orig_max_area, orig_min_area);
29708 oomph_info <<
"Max./min. element size in original mesh: " << orig_max_area
29709 <<
" " << orig_min_area << std::endl;
29717 bool check_only =
true;
29718 bool outer_boundary_update_necessary =
false;
29719 bool inner_boundary_update_necessary =
false;
29720 bool inner_open_boundary_update_necessary =
false;
29724 const unsigned nouter = this->Outer_boundary_pt.size();
29726 if (this->is_automatic_creation_of_vertices_on_boundaries_allowed())
29729 for (
unsigned i_outer = 0; i_outer < nouter; i_outer++)
29731 outer_boundary_update_necessary = this->update_polygon_using_face_mesh(
29732 this->Outer_boundary_pt[i_outer], check_only);
29734 if (outer_boundary_update_necessary)
break;
29739 if (!outer_boundary_update_necessary)
29743 const unsigned nhole = this->Internal_polygon_pt.size();
29745 inner_boundary_update_necessary =
29746 this->surface_remesh_for_inner_hole_boundaries(internal_point_coord,
29751 if (!inner_boundary_update_necessary)
29753 const unsigned n_open_polyline = this->Internal_open_curve_pt.size();
29755 for (
unsigned i = 0;
i < n_open_polyline;
i++)
29757 inner_open_boundary_update_necessary =
29758 this->update_open_curve_using_face_mesh(
29759 this->Internal_open_curve_pt[
i], check_only);
29761 if (inner_open_boundary_update_necessary)
break;
29773#ifdef OOMPH_HAS_MPI
29778 int adapt_this_processor = 0;
29779 if (this->is_mesh_distributed())
29782 if ((Nrefined > 0) || (Nunrefined > max_keep_unrefined()) ||
29783 (min_angle < min_permitted_angle()) ||
29784 (outer_boundary_update_necessary) ||
29785 (inner_boundary_update_necessary) ||
29786 (inner_open_boundary_update_necessary))
29788 adapt_this_processor = 1;
29795 MPI_Allreduce(&adapt_this_processor,
29800 comm_pt->mpi_comm());
29808 if ((Nrefined > 0) || (Nunrefined > max_keep_unrefined()) ||
29809 (min_angle < min_permitted_angle()) ||
29810 (outer_boundary_update_necessary) ||
29811 (inner_boundary_update_necessary) ||
29812 (inner_open_boundary_update_necessary) || (adapt_all))
29814 if (!((Nrefined > 0) || (Nunrefined > max_keep_unrefined())))
29816 if ((outer_boundary_update_necessary) ||
29817 (inner_boundary_update_necessary) ||
29818 (inner_open_boundary_update_necessary))
29821 <<
"Mesh regeneration triggered by inaccurate interface/surface\n"
29822 <<
"representation; setting Nrefined to number of elements.\n"
29823 <<
"outer_boundary_update_necessary : "
29824 << outer_boundary_update_necessary <<
"\n"
29825 <<
"inner_boundary_update_necessary : "
29826 << inner_boundary_update_necessary <<
"\n"
29827 <<
"inner_open_boundary_update_necessary: "
29828 << inner_open_boundary_update_necessary <<
"\n";
29829 Nrefined = nelement();
29833 oomph_info <<
"Mesh regeneration triggered by min angle criterion;\n"
29834 <<
"setting Nrefined to number of elements.\n";
29835 Nrefined = nelement();
29842#ifdef OOMPH_HAS_MPI
29843 else if (this->is_mesh_distributed() && adapt_this_processor == 0 &&
29846 oomph_info <<
"Mesh regeneration triggered by (" << adapt_all
29847 <<
") processor(s) "
29848 <<
"that require(s)\n adaptation\n";
29863 add_vertices_for_non_deletion();
29868#ifdef OOMPH_HAS_MPI
29873 if (this->is_mesh_distributed())
29875 synchronize_shared_boundary_connections();
29888 if (this->is_automatic_creation_of_vertices_on_boundaries_allowed())
29891 unsigned nhole = this->Internal_polygon_pt.size();
29893 this->surface_remesh_for_inner_hole_boundaries(internal_point_coord);
29896 for (
unsigned i_outer = 0; i_outer < nouter; i_outer++)
29898 this->update_polygon_using_face_mesh(
29899 this->Outer_boundary_pt[i_outer]);
29904 unsigned n_open_polyline = this->Internal_open_curve_pt.size();
29905 for (
unsigned i = 0;
i < n_open_polyline;
i++)
29907 this->update_open_curve_using_face_mesh(
29908 this->Internal_open_curve_pt[
i]);
29917 const unsigned ninternal = this->Internal_polygon_pt.size();
29918 for (
unsigned i_internal = 0; i_internal < ninternal; i_internal++)
29920 this->update_polygon_using_elements_area(
29921 this->Internal_polygon_pt[i_internal], target_area);
29926 for (
unsigned i_outer = 0; i_outer < nouter; i_outer++)
29928 this->update_polygon_using_elements_area(
29929 this->Outer_boundary_pt[i_outer], target_area);
29934 const unsigned n_open_polyline = this->Internal_open_curve_pt.size();
29935 for (
unsigned i = 0;
i < n_open_polyline;
i++)
29937 this->update_open_curve_using_elements_area(
29938 this->Internal_open_curve_pt[
i], target_area);
29949#ifdef OOMPH_HAS_MPI
29951 if (this->is_mesh_distributed())
29954 const unsigned my_rank = this->communicator_pt()->my_rank();
29957 const unsigned n_curves = this->nshared_boundary_curves(my_rank);
29959 for (
unsigned nc = 0; nc < n_curves; nc++)
29962 this->update_shared_curve_using_elements_area(
29963 this->Shared_boundary_polyline_pt[my_rank][nc],
29990 const unsigned n_boundary = this->nboundary();
29992 const double t_start_first_stage_segments_connectivity =
29998#ifdef OOMPH_HAS_MPI
30001 if (this->is_mesh_distributed())
30003 this->Assigned_segments_initial_zeta_values.clear();
30011 for (
unsigned b = 0; b < n_boundary; ++b)
30016#ifdef OOMPH_HAS_MPI
30017 if (this->is_mesh_distributed())
30023 this->compute_boundary_segments_connectivity_and_initial_zeta_values(
30032 if (this->boundary_geom_object_pt(b) == 0)
30034 this->
template setup_boundary_coordinates<ELEMENT>(b);
30040#ifdef OOMPH_HAS_MPI
30041 if (this->is_mesh_distributed())
30046 this->synchronize_boundary_coordinates(b);
30055 const double t_total_first_stage_segments_connectivity =
30066#ifdef OOMPH_HAS_MPI
30081 if (this->is_mesh_distributed())
30085 this->create_distributed_domain_representation(tmp_outer_polygons_pt,
30086 tmp_open_curves_pt);
30089 this->create_temporary_boundary_connections(tmp_outer_polygons_pt,
30090 tmp_open_curves_pt);
30106 restore_boundary_connections(resume_initial_connection_polyline_pt,
30107 resume_final_connection_polyline_pt);
30113 unsigned n_region = this->nregion();
30117 this->Regions_coordinates.begin();
30118 it != this->Regions_coordinates.end();
30125 unsigned region_id = it->first;
30128 oomph_info <<
"Region " << region_id <<
": " << it->second[0] <<
" "
30129 << it->second[1] <<
" ";
30132 unsigned n_region_element = this->nregion_element(region_id);
30133 if (n_region_element > 0)
30137 this->region_element_pt(region_id, 0);
30140 for (
unsigned n = 0; n < 3; n++)
30142 Node*
const nod_pt = elem_pt->
node_pt(n);
30143 for (
unsigned i = 0;
i < 2;
i++)
30145 centroid[
i] += nod_pt->x(
i);
30148 for (
unsigned i = 0;
i < 2;
i++)
30153 it->second = centroid;
30155 oomph_info <<
" , " << it->second[0] <<
" " << it->second[1]
30184#ifdef OOMPH_HAS_MPI
30185 if (!this->is_mesh_distributed())
30189 closed_curve_pt.resize(nouter);
30190 for (
unsigned i = 0;
i < nouter;
i++)
30192 closed_curve_pt[
i] = this->Outer_boundary_pt[
i];
30196 const unsigned n_holes = this->Internal_polygon_pt.size();
30197 hole_pt.resize(n_holes);
30198 for (
unsigned i = 0;
i < n_holes;
i++)
30200 hole_pt[
i] = this->Internal_polygon_pt[
i];
30204 const unsigned n_open_curves = this->Internal_open_curve_pt.size();
30205 open_curves_pt.resize(n_open_curves);
30206 for (
unsigned i = 0;
i < n_open_curves;
i++)
30208 open_curves_pt[
i] = this->Internal_open_curve_pt[
i];
30214#ifdef OOMPH_HAS_MPI
30219 const unsigned n_tmp_outer = tmp_outer_polygons_pt.size();
30220 closed_curve_pt.resize(n_tmp_outer);
30221 for (
unsigned i = 0;
i < n_tmp_outer;
i++)
30223 closed_curve_pt[
i] = tmp_outer_polygons_pt[
i];
30227 const unsigned n_open_curves = tmp_open_curves_pt.size();
30228 open_curves_pt.resize(n_open_curves);
30229 for (
unsigned i = 0;
i < n_open_curves;
i++)
30231 open_curves_pt[
i] = tmp_open_curves_pt[
i];
30260 this->Extra_holes_coordinates;
30264 this->Regions_coordinates;
30267 if (this->Use_attributes)
30273 if (!this->is_automatic_creation_of_vertices_on_boundaries_allowed())
30275 triangle_mesh_parameters
30281#ifdef OOMPH_HAS_MPI
30282 if (this->is_mesh_distributed())
30295 if (solid_mesh_pt != 0)
30298 triangle_mesh_parameters, this->Time_stepper_pt);
30303 triangle_mesh_parameters, this->Time_stepper_pt);
30306 if (Print_timings_level_adaptation > 2)
30308 oomph_info <<
"CPU for building background mesh: "
30315 const double this_max_element_size = this->max_element_size();
30316 const double this_min_element_size = this->min_element_size();
30321 const double this_min_permitted_angle = this->min_permitted_angle();
30327#ifdef OOMPH_HAS_MPI
30331 if (this->is_mesh_distributed())
30335 if (this->nshared_boundary_overlaps_internal_boundary() > 0)
30340 this->shared_boundary_overlaps_internal_boundary();
30345 this->shared_boundaries_ids();
30366 this->boundary_geom_object_pt();
30371 this->boundary_coordinate_limits();
30373 const double t_start_second_stage_segments_connectivity =
30376 for (
unsigned b = 0; b < n_boundary; b++)
30381#ifdef OOMPH_HAS_MPI
30382 if (this->is_mesh_distributed())
30399 tmp_new_mesh_pt->template setup_boundary_coordinates<ELEMENT>(b);
30403 const double t_total_second_stage_segments_connectivity =
30410 for (
unsigned b = 0; b < n_boundary; b++)
30412 this->snap_nodes_onto_boundary(tmp_new_mesh_pt, b);
30415 const double t_total_snap_nodes_bg_mesh =
30418 if (Print_timings_level_adaptation > 2)
30420 oomph_info <<
"CPU for snapping nodes onto boundaries "
30421 <<
"(background mesh): " << t_total_snap_nodes_bg_mesh
30426 if (Mesh_update_fct_pt != 0)
30428 Mesh_update_fct_pt(tmp_new_mesh_pt);
30461 bool use_eulerian_coords =
false;
30462 if (solid_mesh_pt != 0)
30464 use_eulerian_coords =
true;
30468#ifdef OOMPH_HAS_CGAL
30472 if (use_eulerian_coords)
30482 if (use_eulerian_coords)
30487 bin_dim[0] = Nbin_x_for_area_transfer;
30488 bin_dim[1] = Nbin_y_for_area_transfer;
30496 std::map<GeneralisedElement*, unsigned> element_number;
30497 unsigned nelem = this->nelement();
30498 for (
unsigned e = 0;
e < nelem;
e++)
30500 element_number[this->element_pt(
e)] =
e;
30503#ifndef OOMPH_HAS_CGAL
30514 if (bin_array_pt == 0)
30517 "Sample point container has to be NonRefineableBinArray",
30518 OOMPH_CURRENT_FUNCTION,
30519 OOMPH_EXCEPTION_LOCATION);
30523 unsigned n_bin = 0;
30524 unsigned max_n_entry = 0;
30525 unsigned min_n_entry = UINT_MAX;
30526 unsigned tot_n_entry = 0;
30527 unsigned n_empty = 0;
30529 n_bin, max_n_entry, min_n_entry, tot_n_entry, n_empty);
30532 <<
" nbin:(" << n_bin <<
")"
30533 <<
" nempty:(" << n_empty <<
")"
30534 <<
" min:(" << min_n_entry <<
")"
30535 <<
" max:(" << max_n_entry <<
")"
30536 <<
" average entries:("
30537 << double(tot_n_entry) / double(n_bin) <<
")" << std::endl;
30542 oomph_info <<
"Going into diffusion bit...\n";
30544 oomph_info <<
"Back from diffusion bit...\n";
30550 unsigned n_bin = 0;
30551 unsigned max_n_entry = 0;
30552 unsigned min_n_entry = UINT_MAX;
30553 unsigned tot_n_entry = 0;
30554 unsigned n_empty = 0;
30556 n_bin, max_n_entry, min_n_entry, tot_n_entry, n_empty);
30559 <<
" nbin:(" << n_bin <<
")"
30560 <<
" nempty:(" << n_empty <<
")"
30561 <<
" min:(" << min_n_entry <<
")"
30562 <<
" max:(" << max_n_entry <<
")"
30563 <<
" average entries:("
30564 << double(tot_n_entry) / double(n_bin) <<
")" << std::endl;
30571 double t_total_map = 0.0;
30574 unsigned counter_map = 0;
30579 const std::map<unsigned,
30584 const unsigned n_bin = bins_pt->size();
30589 bin_min_target_area.resize(n_bin);
30590 for (
unsigned u = 0;
u < n_bin;
u++)
30592 bin_min_target_area[
u] = 0.0;
30599 for (IT it = bins_pt->begin(); it != bins_pt->end(); it++)
30602 unsigned ib = (*it).first;
30605 const unsigned n_ele_bin = (*it).second.size();
30608 for (
unsigned ee = 0; ee < n_ele_bin; ee++)
30613 const unsigned ele_number = element_number[ele_pt];
30622 if (bin_min_target_area[ib] != 0)
30624 bin_min_target_area[ib] =
30625 std::min(bin_min_target_area[ib], target_area[ele_number]);
30629 bin_min_target_area[ib] = target_area[ele_number];
30636 oomph_info <<
"CPU for map[counter=" << counter_map
30637 <<
"]: " << t_total_map << std::endl;
30641 const bool output_bins =
false;
30644 unsigned length = bin_min_target_area.size();
30645 for (
unsigned u = 0;
u < length;
u++)
30648 <<
",target area: " << bin_min_target_area[
u] << std::endl;
30659#ifdef OOMPH_HAS_MPI
30661 unsigned n_ele_need_refinement = 0;
30665 double t_total_third_stage_segments_connectivity = 0.0;
30668 double t_total_transfer_target_areas = 0.0;
30671 double t_total_limit_target_areas = 0.0;
30674 double t_total_create_new_adapted_mesh = 0.0;
30677 double t_total_snap_nodes = 0.0;
30680 double t_total_wait_other_processors = 0.0;
30694 nelem = tmp_new_mesh_pt->
nelement();
30699 for (
unsigned e = 0;
e < nelem;
e++)
30702 dynamic_cast<ELEMENT*
>(tmp_new_mesh_pt->
element_pt(
e));
30703 unsigned nint = el_pt->integral_pt()->nweight();
30704 for (
unsigned ipt = 0; ipt < nint; ipt++)
30708 for (
unsigned i = 0;
i < 2;
i++)
30710 s[
i] = el_pt->integral_pt()->knot(ipt,
i);
30714 el_pt->interpolated_x(
s,
x);
30721 unsigned max_sample_points =
30722 Max_sample_points_for_limited_locate_zeta_during_target_area_transfer;
30725 ->limited_locate_zeta(
x, max_sample_points, geom_obj_pt,
s);
30727 if (geom_obj_pt == 0)
30729 std::stringstream error_message;
30730 error_message <<
"Limited locate zeta failed for zeta = [ "
30731 <<
x[0] <<
" " <<
x[1] <<
" ]. Makes no sense!\n";
30733 OOMPH_CURRENT_FUNCTION,
30734 OOMPH_EXCEPTION_LOCATION);
30743 std::stringstream error_message;
30744 error_message <<
"Cast to FE for GeomObject returned by "
30745 "limited locate zeta failed for zeta = [ "
30746 <<
x[0] <<
" " <<
x[1] <<
" ]. Makes no sense!\n";
30748 OOMPH_CURRENT_FUNCTION,
30749 OOMPH_EXCEPTION_LOCATION);
30756 double tg_area = target_area[element_number[fe_pt]];
30763 if (new_transferred_target_area[
e] != 0)
30765 new_transferred_target_area[
e] =
30766 std::min(new_transferred_target_area[
e], tg_area);
30770 new_transferred_target_area[
e] = tg_area;
30780 int bin_number = 0;
30781 bin_array_pt->
get_bin(
x, bin_number);
30784 if (bin_number < 0)
30787 std::stringstream error_message;
30788 error_message <<
"Very odd -- we're looking for a point[ " <<
x[0]
30789 <<
" " <<
x[1] <<
" ] that's not even \n"
30790 <<
"located within the bin boundaries.\n";
30792 "RefineableTriangleMesh::adapt()",
30793 OOMPH_EXCEPTION_LOCATION);
30801 if (new_transferred_target_area[
e] != 0)
30803 new_transferred_target_area[
e] =
30804 std::min(new_transferred_target_area[
e],
30805 bin_min_target_area[bin_number]);
30809 new_transferred_target_area[
e] =
30810 bin_min_target_area[bin_number];
30822 const bool output_target_areas =
false;
30823 if (output_target_areas)
30825 unsigned length = new_transferred_target_area.size();
30826 for (
unsigned u = 0;
u < length;
u++)
30829 <<
",target area: " << new_transferred_target_area[
u]
30833 oomph_info <<
"Time for loop over integration points in new mesh: "
30866 const double t_sub_total_transfer_target_areas =
30869 if (Print_timings_level_adaptation > 2)
30872 const unsigned n_element = this->nelement();
30874 const unsigned n_element_background = tmp_new_mesh_pt->
nelement();
30876 oomph_info <<
"CPU for transfer of target areas "
30877 <<
"[n_ele_old_mesh=" << n_element
30878 <<
", n_ele_background_mesh=" << n_element_background
30879 <<
"] (iter " << iter
30880 <<
"): " << t_sub_total_transfer_target_areas << std::endl;
30884 t_total_transfer_target_areas += t_sub_total_transfer_target_areas;
30899#ifdef OOMPH_HAS_MPI
30900 unsigned n_ele_need_refinement_iter = 0;
30912 const unsigned nel_new = tmp_new_mesh_pt->
nelement();
30914 for (
unsigned e = 0;
e < nel_new;
e++)
30920 const double new_area = new_transferred_target_area[
e];
30921 if (new_area <= 0.0)
30923 std::ostringstream error_stream;
30925 <<
"This shouldn't happen! Element whose centroid is at "
30927 f_ele_pt->
node_pt(2)->x(0)) /
30931 f_ele_pt->
node_pt(2)->x(1)) /
30934 <<
" has no target area assigned\n";
30936 OOMPH_CURRENT_FUNCTION,
30937 OOMPH_EXCEPTION_LOCATION);
30943 new_target_area[
e] = new_area;
30944 if (new_target_area[
e] < f_ele_pt->
size() / 3.0)
30946 new_target_area[
e] = f_ele_pt->
size() / 3.0;
30964#ifdef OOMPH_HAS_MPI
30966 n_ele_need_refinement_iter++;
30977 const double t_sub_total_limit_target_areas =
30981 t_total_limit_target_areas += t_sub_total_limit_target_areas;
30983 if (Print_timings_level_adaptation > 2)
30986 const unsigned n_element = this->nelement();
30988 const unsigned n_element_background = tmp_new_mesh_pt->
nelement();
30990 oomph_info <<
"CPU for limiting target areas "
30991 <<
"[n_ele_old_mesh=" << n_element
30992 <<
", n_ele_background_mesh=" << n_element_background
30993 <<
"] (iter " << iter
30994 <<
"): " << t_sub_total_limit_target_areas << std::endl;
31000 <<
"All area adjustments accommodated by max. permitted area"
31001 <<
" reduction \n";
31005 oomph_info <<
"NOT all area adjustments accommodated by max. "
31006 <<
"permitted area reduction \n";
31022 if (solid_mesh_pt != 0)
31026 tmp_new_triangulateio,
31027 this->Time_stepper_pt,
31028 this->Use_attributes,
31029 this->Allow_automatic_creation_of_vertices_on_boundaries,
31030 this->communicator_pt());
31037 tmp_new_triangulateio,
31038 this->Time_stepper_pt,
31039 this->Use_attributes,
31040 this->Allow_automatic_creation_of_vertices_on_boundaries,
31041 this->communicator_pt());
31045 const double t_sub_total_create_new_adapted_mesh =
31049 t_total_create_new_adapted_mesh += t_sub_total_create_new_adapted_mesh;
31051 if (Print_timings_level_adaptation > 2)
31054 const unsigned n_element_new_adapted_mesh = new_mesh_pt->
nelement();
31056 oomph_info <<
"CPU for creation of new adapted mesh "
31057 << t_sub_total_create_new_adapted_mesh
31058 <<
"[nele=" << n_element_new_adapted_mesh <<
"] (iter "
31059 << iter <<
"): " << t_sub_total_create_new_adapted_mesh
31063#ifdef OOMPH_HAS_MPI
31074 if (this->nshared_boundary_overlaps_internal_boundary() > 0)
31079 this->shared_boundary_overlaps_internal_boundary();
31101 this->boundary_geom_object_pt();
31106 this->boundary_coordinate_limits();
31108 const double t_start_third_stage_segments_connectivity =
31111 for (
unsigned b = 0; b < n_boundary; b++)
31120#ifdef OOMPH_HAS_MPI
31121 if (this->is_mesh_distributed())
31138 new_mesh_pt->template setup_boundary_coordinates<ELEMENT>(b);
31142 t_total_third_stage_segments_connectivity +=
31149 for (
unsigned b = 0; b < n_boundary; b++)
31151 this->snap_nodes_onto_boundary(new_mesh_pt, b);
31154 const double t_sub_total_snap_nodes_new_mesh =
31158 t_total_snap_nodes += t_sub_total_snap_nodes_new_mesh;
31160 if (Print_timings_level_adaptation > 2)
31162 oomph_info <<
"CPU for snapping nodes onto boundaries (new mesh) "
31163 <<
"(iter " << iter
31164 <<
"): " << t_sub_total_snap_nodes_new_mesh << std::endl;
31168 if (Mesh_update_fct_pt != 0)
31170 Mesh_update_fct_pt(new_mesh_pt);
31180 this->Time_stepper_pt,
false);
31187 delete tmp_new_mesh_pt;
31189#ifdef OOMPH_HAS_MPI
31193 if (n_ele_need_refinement_iter == n_ele_need_refinement)
31199 n_ele_need_refinement = n_ele_need_refinement_iter;
31209#ifdef OOMPH_HAS_MPI
31210 if (this->is_mesh_distributed())
31220 unsigned this_processor_requires_another_iteration = 1;
31225 this_processor_requires_another_iteration = 0;
31227 int nproc_not_done = this_processor_requires_another_iteration;
31232 MPI_Allreduce(&this_processor_requires_another_iteration,
31237 comm_pt->mpi_comm());
31239 if (nproc_not_done > 0)
31242 <<
"At least one processors requires further refinement. "
31243 <<
"Go for another iteration." << std::endl;
31249 const double t_sub_total_wait_other_processors =
31254 t_total_wait_other_processors += t_sub_total_wait_other_processors;
31256 if (Print_timings_level_adaptation > 2)
31258 oomph_info <<
"CPU for waiting other processors "
31259 <<
"(iter " << iter
31260 <<
"): " << t_sub_total_wait_other_processors
31272 oomph_info <<
"Going for another iteration. Current iteration ("
31273 << iter <<
")" << std::endl;
31276 tmp_new_mesh_pt = new_mesh_pt;
31284 delete mesh_geom_obj_pt;
31286 oomph_info <<
"CPU for iterative generation of new mesh (TOTAL): "
31289 if (Print_timings_level_adaptation > 1)
31291 oomph_info <<
"-- CPU for creating new adapted meshes (TOTAL): "
31292 << t_total_create_new_adapted_mesh << std::endl;
31294 oomph_info <<
"-- CPU for limiting target areas (TOTAL): "
31295 << t_total_limit_target_areas << std::endl;
31297 oomph_info <<
"-- CPU for transferring target areas (TOTAL): "
31298 << t_total_transfer_target_areas << std::endl;
31300 oomph_info <<
"-- CPU for waiting other processors (TOTAL): "
31301 << t_total_wait_other_processors << std::endl;
31313 if (!Disable_projection)
31319 if (Print_timings_projection)
31328 oomph_info <<
"About to begin projection.\n";
31337#ifdef OOMPH_HAS_MPI
31338 if (this->is_mesh_distributed())
31346 Time* backed_up_time_pt = this->Time_stepper_pt->time_pt();
31356 project_problem_pt->
mesh_pt() = new_mesh_pt;
31361 if (!this->use_iterative_solver_for_projection())
31367 project_problem_pt->
project(
this);
31370 this->Time_stepper_pt->time_pt() = backed_up_time_pt;
31381 project_problem_pt->
mesh_pt() = new_mesh_pt;
31387 if (!this->use_iterative_solver_for_projection())
31393 project_problem_pt->
project(
this);
31397 if (Print_timings_projection)
31406 const double tt_projection =
31409 if (Print_timings_level_adaptation > 1)
31412 const unsigned n_element = this->nelement();
31414 const unsigned n_element_new = new_mesh_pt->
nelement();
31415 oomph_info <<
"CPU for projection (in mesh adaptation) "
31416 <<
"[n_ele_old_mesh=" << n_element
31417 <<
", n_ele_new_mesh=" << n_element_new
31418 <<
"]: " << tt_projection << std::endl;
31423#ifdef OOMPH_HAS_MPI
31424 if (this->is_mesh_distributed())
31428 unsigned n_this_element_new = n_element_new;
31429 unsigned n_max_element_new_global = 0;
31431 MPI_Reduce(&n_this_element_new,
31432 &n_max_element_new_global,
31437 this->communicator_pt()->mpi_comm());
31440 double tt_this_projection = tt_projection;
31441 double tt_global_min_projection = 0.0;
31442 double tt_global_max_projection = 0.0;
31445 MPI_Reduce(&tt_this_projection,
31446 &tt_global_min_projection,
31451 this->communicator_pt()->mpi_comm());
31452 MPI_Reduce(&tt_this_projection,
31453 &tt_global_max_projection,
31458 this->communicator_pt()->mpi_comm());
31460 if (this->communicator_pt()->my_rank() == 0)
31462 oomph_info <<
"CPU for projection global (MIN): "
31463 << tt_global_min_projection << std::endl;
31464 oomph_info <<
"CPU for projection global (MAX) "
31465 <<
"[n_max_ele_new_global=" << n_max_element_new_global
31466 <<
"]: " << tt_global_max_projection << std::endl;
31468 std::cerr <<
"CPU for projection global (MIN): "
31469 << tt_global_min_projection << std::endl;
31470 std::cerr <<
"CPU for projection global (MAX): "
31471 <<
"[n_max_ele_new_global=" << n_max_element_new_global
31472 <<
"]: " << tt_global_max_projection << std::endl;
31482 oomph_info <<
"CPU for projection of solution onto new mesh: "
31486 delete project_problem_pt;
31491 oomph_info <<
"Projection disabled! The new mesh will contain zeros"
31502 unsigned nnod = nnode();
31503 for (
unsigned j = nnod; j > 0; j--)
31505 delete Node_pt[j - 1];
31506 Node_pt[j - 1] = 0;
31508 unsigned nel = nelement();
31509 for (
unsigned e = nel;
e > 0;
e--)
31511 delete Element_pt[
e - 1];
31512 Element_pt[
e - 1] = 0;
31517 nnod = new_mesh_pt->
nnode();
31518 Node_pt.resize(nnod);
31520 Element_pt.resize(nel);
31521 for (
unsigned j = 0; j < nnod; j++)
31523 Node_pt[j] = new_mesh_pt->
node_pt(j);
31525 for (
unsigned e = 0;
e < nel;
e++)
31532 unsigned nbound = 0;
31534#ifdef OOMPH_HAS_MPI
31538 if (this->is_mesh_distributed())
31552 nbound = n_boundary;
31555 Boundary_element_pt.resize(nbound);
31556 Face_index_at_boundary.resize(nbound);
31557 Boundary_node_pt.resize(nbound);
31558 for (
unsigned b = 0; b < nbound; b++)
31561 Boundary_element_pt[b].resize(nel);
31562 Face_index_at_boundary[b].resize(nel);
31563 for (
unsigned e = 0;
e < nel;
e++)
31566 Face_index_at_boundary[b][
e] =
31570 Boundary_node_pt[b].resize(nnod);
31571 for (
unsigned j = 0; j < nnod; j++)
31578 unsigned n_region = new_mesh_pt->
nregion();
31583 this->Region_attribute.resize(n_region);
31584 for (
unsigned r = 0; r < n_region; r++)
31588 unsigned r_id =
static_cast<unsigned>(this->Region_attribute[r]);
31591 this->Region_element_pt[r_id].resize(n_region_element);
31592 for (
unsigned e = 0;
e < n_region_element;
e++)
31594 this->Region_element_pt[r_id][
e] =
31600 this->Boundary_region_element_pt.resize(nbound);
31601 this->Face_index_region_at_boundary.resize(nbound);
31604 for (
unsigned b = 0; b < nbound; ++b)
31606 for (
unsigned rr = 0; rr < n_region; rr++)
31609 unsigned r =
static_cast<unsigned>(this->Region_attribute[rr]);
31611 unsigned n_boundary_el_in_region =
31614 if (n_boundary_el_in_region > 0)
31617 this->Boundary_region_element_pt[b][r].resize(
31618 n_boundary_el_in_region);
31619 this->Face_index_region_at_boundary[b][r].resize(
31620 n_boundary_el_in_region);
31623 for (
unsigned e = 0;
e < n_boundary_el_in_region; ++
e)
31625 this->Boundary_region_element_pt[b][r][
e] =
31627 this->Face_index_region_at_boundary[b][r][
e] =
31641#ifdef OOMPH_HAS_MPI
31642 if (this->is_mesh_distributed())
31647 if (this->is_mesh_distributed())
31649 this->Halo_node_pt.clear();
31650 this->Root_halo_element_pt.clear();
31652 this->Haloed_node_pt.clear();
31653 this->Root_haloed_element_pt.clear();
31655 this->External_halo_node_pt.clear();
31656 this->External_halo_element_pt.clear();
31658 this->External_haloed_node_pt.clear();
31659 this->External_haloed_element_pt.clear();
31664 this->reset_shared_boundary_elements_and_nodes();
31675 this->shared_boundaries_in_this_processor(
31676 my_rank_shared_boundaries_ids);
31679 const unsigned nmy_rank_shd_bnd = my_rank_shared_boundaries_ids.size();
31682 for (
unsigned i = 0;
i < nmy_rank_shd_bnd;
i++)
31685 const unsigned shd_bnd_id = my_rank_shared_boundaries_ids[
i];
31688 this->Boundary_element_pt[shd_bnd_id].clear();
31692 const unsigned tmp_nnodes = this->nshared_boundary_node(shd_bnd_id);
31693 for (
unsigned n = 0; n < tmp_nnodes; n++)
31695 Node* tmp_node_pt = this->boundary_node_pt(shd_bnd_id, n);
31696 tmp_node_pt->remove_from_boundary(shd_bnd_id);
31702 this->set_nboundary(n_boundary);
31706 this->sort_nodes_on_shared_boundaries();
31709 this->reset_halo_haloed_scheme();
31713 for (
unsigned b = 0; b < n_boundary; b++)
31715 if (this->boundary_geom_object_pt(b) != 0)
31718 this->set_nboundary_segment_node(b, nsegments);
31723 resume_boundary_connections(resume_initial_connection_polyline_pt,
31724 resume_final_connection_polyline_pt);
31735 this->snap_nodes_onto_geometric_objects();
31743 this->Triangulateio =
31751 delete new_mesh_pt;
31754 if (Print_timings_level_adaptation > 2)
31758 oomph_info <<
"CPU for segments connectivity (first stage) [sec]: "
31759 << t_total_first_stage_segments_connectivity << std::endl;
31760 oomph_info <<
"CPU for segments connectivity (second stage) [sec]: "
31761 << t_total_second_stage_segments_connectivity << std::endl;
31762 oomph_info <<
"CPU for segments connectivity (third stage) [sec]: "
31763 << t_total_third_stage_segments_connectivity << std::endl;
31766 if (Print_timings_level_adaptation > 1)
31768 const double t_total_segments_connectivity =
31769 t_total_first_stage_segments_connectivity +
31770 t_total_second_stage_segments_connectivity +
31771 t_total_third_stage_segments_connectivity;
31773 oomph_info <<
"CPU for segments connectivity (TOTAL) [sec]: "
31774 << t_total_segments_connectivity << std::endl;
31776 if (Print_timings_level_adaptation > 2)
31779 oomph_info <<
"CPU for snapping nodes onto boundaries "
31780 <<
"(new mesh): " << t_total_snap_nodes << std::endl;
31783 t_total_snap_nodes += t_total_snap_nodes_bg_mesh;
31784 oomph_info <<
"CPU for snapping nodes onto boundaries (TOTAL): "
31785 << t_total_snap_nodes << std::endl;
31788 double max_area = 0.0;
31789 double min_area = 0.0;
31791 this->max_and_min_element_size(max_area, min_area);
31792 oomph_info <<
"Max/min element size in adapted mesh: " << max_area <<
" "
31793 << min_area << std::endl;
31795 oomph_info <<
"CPU time for final bits [sec]: "
31800 oomph_info <<
"Not enough benefit in adaptation.\n";
31806 oomph_info <<
"CPU time for adaptation [sec]: " << CPU_for_adaptation
31812#ifdef OOMPH_HAS_MPI
31813 if (this->is_mesh_distributed())
31818 const unsigned n_proc = comm_pt->nproc();
31819 if (Print_timings_level_adaptation > 1 && n_proc > 1)
31821 double global_min_CPU_for_adaptation = 0.0;
31822 double global_max_CPU_for_adaptation = 0.0;
31823 double global_average_CPU_for_adaptation = 0.0;
31826 MPI_Reduce(&CPU_for_adaptation,
31827 &global_min_CPU_for_adaptation,
31832 comm_pt->mpi_comm());
31833 MPI_Reduce(&CPU_for_adaptation,
31834 &global_max_CPU_for_adaptation,
31839 comm_pt->mpi_comm());
31840 MPI_Reduce(&CPU_for_adaptation,
31841 &global_average_CPU_for_adaptation,
31846 comm_pt->mpi_comm());
31849 const unsigned my_rank = comm_pt->my_rank();
31853 << global_min_CPU_for_adaptation << std::endl;
31855 << global_max_CPU_for_adaptation << std::endl;
31856 oomph_info <<
"CPU for adaptation (AVERAGE): "
31857 << global_average_CPU_for_adaptation / n_proc << std::endl;
31876 template<
class ELEMENT>
31881 Boundary_connections_pt.clear();
31888 std::set<unsigned> boundary_id_with_connections;
31895 const unsigned n_outer_boundaries = this->Outer_boundary_pt.size();
31898 for (
unsigned i = 0;
i < n_outer_boundaries;
i++)
31904 const unsigned n_polyline = tmp_polygon_pt->
npolyline();
31906 for (
unsigned p = 0; p < n_polyline; p++)
31915 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
31919 boundary_id_with_connections.insert(bnd_id);
31922 const unsigned dst_bnd_id =
31927 boundary_id_with_connections.insert(dst_bnd_id);
31935 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
31939 boundary_id_with_connections.insert(bnd_id);
31942 const unsigned dst_bnd_id =
31947 boundary_id_with_connections.insert(dst_bnd_id);
31960 const unsigned n_internal_boundaries = this->Internal_polygon_pt.size();
31963 for (
unsigned i = 0;
i < n_internal_boundaries;
i++)
31969 const unsigned n_polyline = tmp_polygon_pt->
npolyline();
31971 for (
unsigned p = 0; p < n_polyline; p++)
31980 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
31984 boundary_id_with_connections.insert(bnd_id);
31987 const unsigned dst_bnd_id =
31992 boundary_id_with_connections.insert(dst_bnd_id);
32000 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
32004 boundary_id_with_connections.insert(bnd_id);
32007 const unsigned dst_bnd_id =
32012 boundary_id_with_connections.insert(dst_bnd_id);
32025 const unsigned n_open_boundaries = this->Internal_open_curve_pt.size();
32028 for (
unsigned i = 0;
i < n_open_boundaries;
i++)
32032 this->Internal_open_curve_pt[
i];
32036 const unsigned n_curve_section = tmp_open_curve_pt->
ncurve_section();
32039 for (
unsigned p = 0; p < n_curve_section; p++)
32050 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
32054 boundary_id_with_connections.insert(bnd_id);
32057 const unsigned dst_bnd_id =
32062 boundary_id_with_connections.insert(dst_bnd_id);
32070 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
32074 boundary_id_with_connections.insert(bnd_id);
32077 const unsigned dst_bnd_id =
32082 boundary_id_with_connections.insert(dst_bnd_id);
32090#ifdef OOMPH_HAS_MPI
32097 if (this->is_mesh_distributed())
32100 const unsigned my_rank = this->communicator_pt()->my_rank();
32103 const unsigned n_shared_curves = this->nshared_boundary_curves(my_rank);
32106 for (
unsigned i = 0;
i < n_shared_curves;
i++)
32110 const unsigned n_polyline = this->nshared_boundary_polyline(my_rank,
i);
32114 for (
unsigned p = 0; p < n_polyline; p++)
32118 this->shared_boundary_polyline_pt(my_rank,
i, p);
32124 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
32128 boundary_id_with_connections.insert(bnd_id);
32131 const unsigned dst_bnd_id =
32136 boundary_id_with_connections.insert(dst_bnd_id);
32144 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
32148 boundary_id_with_connections.insert(bnd_id);
32151 const unsigned dst_bnd_id =
32156 boundary_id_with_connections.insert(dst_bnd_id);
32174 std::map<unsigned, Vector<Vector<Node*>>> bnd_sorted_segment_node_pt;
32177 for (std::set<unsigned>::iterator it = boundary_id_with_connections.begin();
32178 it != boundary_id_with_connections.end();
32182 const unsigned bnd_id = (*it);
32183#ifdef OOMPH_HAS_MPI
32185 if (this->is_mesh_distributed())
32188 const unsigned init_shd_bnd_id = this->initial_shared_boundary_id();
32190 if (bnd_id >= init_shd_bnd_id)
32198 get_shared_boundary_segment_nodes_helper(bnd_id, tmp_shared_nodes_pt);
32201 bnd_sorted_segment_node_pt[bnd_id] = tmp_shared_nodes_pt;
32212 get_boundary_segment_nodes_helper(bnd_id, tmp_boundary_nodes_pt);
32215 bnd_sorted_segment_node_pt[bnd_id] = tmp_boundary_nodes_pt;
32229 get_boundary_segment_nodes_helper(bnd_id, tmp_boundary_nodes_pt);
32232 bnd_sorted_segment_node_pt[bnd_id] = tmp_boundary_nodes_pt;
32246 for (
unsigned i = 0;
i < n_outer_boundaries;
i++)
32252 const unsigned n_polyline = tmp_polygon_pt->
npolyline();
32254 for (
unsigned p = 0; p < n_polyline; p++)
32263 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
32266 const unsigned dst_bnd_id =
32270 const unsigned dst_chunk =
32275 bnd_sorted_segment_node_pt[bnd_id];
32279 bnd_sorted_segment_node_pt[dst_bnd_id];
32283 add_non_delete_vertices_from_boundary_helper(
32284 src_bnd_node_pt, dst_bnd_node_pt, dst_bnd_id, dst_chunk);
32292 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
32295 const unsigned dst_bnd_id =
32299 const unsigned dst_chunk =
32304 bnd_sorted_segment_node_pt[bnd_id];
32308 bnd_sorted_segment_node_pt[dst_bnd_id];
32312 add_non_delete_vertices_from_boundary_helper(
32313 src_bnd_node_pt, dst_bnd_node_pt, dst_bnd_id, dst_chunk);
32325 for (
unsigned i = 0;
i < n_internal_boundaries;
i++)
32331 const unsigned n_polyline = tmp_polygon_pt->
npolyline();
32333 for (
unsigned p = 0; p < n_polyline; p++)
32342 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
32345 const unsigned dst_bnd_id =
32349 const unsigned dst_chunk =
32354 bnd_sorted_segment_node_pt[bnd_id];
32358 bnd_sorted_segment_node_pt[dst_bnd_id];
32362 add_non_delete_vertices_from_boundary_helper(
32363 src_bnd_node_pt, dst_bnd_node_pt, dst_bnd_id, dst_chunk);
32371 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
32374 const unsigned dst_bnd_id =
32378 const unsigned dst_chunk =
32383 bnd_sorted_segment_node_pt[bnd_id];
32387 bnd_sorted_segment_node_pt[dst_bnd_id];
32391 add_non_delete_vertices_from_boundary_helper(
32392 src_bnd_node_pt, dst_bnd_node_pt, dst_bnd_id, dst_chunk);
32404 for (
unsigned i = 0;
i < n_open_boundaries;
i++)
32408 this->Internal_open_curve_pt[
i];
32412 const unsigned n_curve_section = tmp_open_curve_pt->
ncurve_section();
32415 for (
unsigned p = 0; p < n_curve_section; p++)
32426 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
32429 const unsigned dst_bnd_id =
32433 const unsigned dst_chunk =
32438 bnd_sorted_segment_node_pt[bnd_id];
32442 bnd_sorted_segment_node_pt[dst_bnd_id];
32446 add_non_delete_vertices_from_boundary_helper(
32447 src_bnd_node_pt, dst_bnd_node_pt, dst_bnd_id, dst_chunk);
32455 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
32458 const unsigned dst_bnd_id =
32462 const unsigned dst_chunk =
32467 bnd_sorted_segment_node_pt[bnd_id];
32471 bnd_sorted_segment_node_pt[dst_bnd_id];
32475 add_non_delete_vertices_from_boundary_helper(
32476 src_bnd_node_pt, dst_bnd_node_pt, dst_bnd_id, dst_chunk);
32484#ifdef OOMPH_HAS_MPI
32491 if (this->is_mesh_distributed())
32494 const unsigned my_rank = this->communicator_pt()->my_rank();
32497 const unsigned n_shared_curves = this->nshared_boundary_curves(my_rank);
32500 for (
unsigned i = 0;
i < n_shared_curves;
i++)
32504 const unsigned n_polyline = this->nshared_boundary_polyline(my_rank,
i);
32508 for (
unsigned p = 0; p < n_polyline; p++)
32512 this->shared_boundary_polyline_pt(my_rank,
i, p);
32518 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
32521 const unsigned dst_bnd_id =
32525 const unsigned dst_chunk =
32530 bnd_sorted_segment_node_pt[bnd_id];
32534 bnd_sorted_segment_node_pt[dst_bnd_id];
32538 add_non_delete_vertices_from_boundary_helper(
32539 src_bnd_node_pt, dst_bnd_node_pt, dst_bnd_id, dst_chunk);
32547 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
32550 const unsigned dst_bnd_id =
32554 const unsigned dst_chunk =
32559 bnd_sorted_segment_node_pt[bnd_id];
32563 bnd_sorted_segment_node_pt[dst_bnd_id];
32567 add_non_delete_vertices_from_boundary_helper(
32568 src_bnd_node_pt, dst_bnd_node_pt, dst_bnd_id, dst_chunk);
32586 template<
class ELEMENT>
32591 const unsigned& dst_bnd_id,
32592 const unsigned& dst_bnd_chunk)
32595 const unsigned n_seg = src_bound_segment_node_pt.size();
32597 for (
unsigned iseg = 0; iseg < n_seg; iseg++)
32600 const unsigned nnode = src_bound_segment_node_pt[iseg].size();
32602 Node* left_node_pt = src_bound_segment_node_pt[iseg][0];
32603 Node* right_node_pt = src_bound_segment_node_pt[iseg][nnode - 1];
32606 const unsigned n_dst_seg = dst_bound_segment_node_pt.size();
32608 for (
unsigned jseg = 0; jseg < n_dst_seg; jseg++)
32611 const unsigned n_dst_node = dst_bound_segment_node_pt[jseg].size();
32614 for (
unsigned jnode = 0; jnode < n_dst_node; jnode++)
32618 Node* tmp_node_pt = dst_bound_segment_node_pt[jseg][jnode];
32621 if (tmp_node_pt == left_node_pt)
32625 vertex[0] = tmp_node_pt->x(0);
32626 vertex[1] = tmp_node_pt->x(1);
32632 Boundary_connections_pt[dst_bnd_id].insert(vertex);
32640 else if (tmp_node_pt == right_node_pt)
32644 vertex[0] = tmp_node_pt->x(0);
32645 vertex[1] = tmp_node_pt->x(1);
32653 Boundary_connections_pt[dst_bnd_id].insert(vertex);
32667#ifdef OOMPH_HAS_MPI
32673 template<
class ELEMENT>
32675 ELEMENT>::synchronize_shared_boundary_connections()
32678 const unsigned nproc = this->communicator_pt()->nproc();
32680 const unsigned my_rank = this->communicator_pt()->my_rank();
32683 for (
unsigned jproc = 0; jproc < nproc; jproc++)
32688 const unsigned n_shd_bnd_jproc = this->nshared_boundaries(my_rank, jproc);
32692 if (jproc != my_rank && n_shd_bnd_jproc > 0)
32712 this->shared_boundaries_ids(my_rank, jproc);
32715 const unsigned n_shd_bnd_jproc = shd_bnd_ids.size();
32717 for (
unsigned ishd_bnd = 0; ishd_bnd < n_shd_bnd_jproc; ishd_bnd++)
32720 const unsigned shd_bnd_id = shd_bnd_ids[ishd_bnd];
32723 this->boundary_polyline_pt(shd_bnd_id);
32728 std::set<Vector<double>> no_delete_vertex;
32731 const bool boundary_receive_connections =
32732 this->boundary_connections(shd_bnd_id, chunk, no_delete_vertex);
32735 const unsigned n_non_delete_vertex = no_delete_vertex.size();
32738 if (boundary_receive_connections && n_non_delete_vertex > 0)
32741 shd_bnd_id_for_non_deletion.push_back(shd_bnd_id);
32743 chunk_for_non_deletion.push_back(chunk);
32745 number_vertices_non_deletion.push_back(n_non_delete_vertex);
32752 no_delete_vertex.begin();
32753 it != no_delete_vertex.end();
32758 tmp_vertices.push_back(vertex);
32762 vertices_for_non_deletion.push_back(tmp_vertices);
32780 MPI_Request request;
32786 const unsigned n_shd_bnd_with_non_delete_vertices =
32787 shd_bnd_id_for_non_deletion.size();
32790 const unsigned size_package = 3;
32792 const unsigned n_unsigned_data_to_send =
32793 n_shd_bnd_with_non_delete_vertices * size_package;
32803 for (
unsigned i = 0;
i < n_shd_bnd_with_non_delete_vertices;
i++)
32806 flat_package_unsigned_send[j++] = shd_bnd_id_for_non_deletion[
i];
32808 flat_package_unsigned_send[j++] = chunk_for_non_deletion[
i];
32810 flat_package_unsigned_send[j++] = number_vertices_non_deletion[
i];
32812 const unsigned n_vertices_non_deletion =
32813 number_vertices_non_deletion[
i];
32816 for (
unsigned h = 0; h < n_vertices_non_deletion; h++)
32818 flat_package_double_send.push_back(
32819 vertices_for_non_deletion[
i][h][0]);
32820 flat_package_double_send.push_back(
32821 vertices_for_non_deletion[
i][h][1]);
32827 int send_proc = jproc;
32828 int recv_proc = jproc;
32829 unsigned send_count_unsigned_values = n_unsigned_data_to_send;
32830 unsigned send_count_double_values = flat_package_double_send.size();
32835 MPI_Isend(&send_count_unsigned_values,
32840 comm_pt->mpi_comm(),
32843 unsigned receive_count_unsigned_values = 0;
32844 MPI_Recv(&receive_count_unsigned_values,
32849 comm_pt->mpi_comm(),
32852 MPI_Wait(&request, MPI_STATUS_IGNORE);
32855 if (send_count_unsigned_values != 0)
32857 MPI_Isend(&flat_package_unsigned_send[0],
32858 send_count_unsigned_values,
32862 comm_pt->mpi_comm(),
32867 if (receive_count_unsigned_values != 0)
32869 flat_package_unsigned_recv.resize(receive_count_unsigned_values);
32870 MPI_Recv(&flat_package_unsigned_recv[0],
32871 receive_count_unsigned_values,
32875 comm_pt->mpi_comm(),
32881 if (send_count_unsigned_values != 0)
32883 MPI_Wait(&request, MPI_STATUS_IGNORE);
32888 MPI_Isend(&send_count_double_values,
32893 comm_pt->mpi_comm(),
32896 unsigned receive_count_double_values = 0;
32897 MPI_Recv(&receive_count_double_values,
32902 comm_pt->mpi_comm(),
32905 MPI_Wait(&request, MPI_STATUS_IGNORE);
32908 if (send_count_double_values != 0)
32910 MPI_Isend(&flat_package_double_send[0],
32911 send_count_double_values,
32915 comm_pt->mpi_comm(),
32920 if (receive_count_double_values != 0)
32922 flat_package_double_recv.resize(receive_count_double_values);
32923 MPI_Recv(&flat_package_double_recv[0],
32924 receive_count_double_values,
32928 comm_pt->mpi_comm(),
32934 if (send_count_double_values != 0)
32936 MPI_Wait(&request, MPI_STATUS_IGNORE);
32964 for (
unsigned i = 0;
i < receive_count_unsigned_values;
i += 3)
32967 const unsigned recv_shd_bnd_id = flat_package_unsigned_recv[
i];
32968 recv_shd_bnd_id_for_non_deletion.push_back(recv_shd_bnd_id);
32970 const unsigned recv_chunk = flat_package_unsigned_recv[
i + 1];
32971 recv_chunk_for_non_deletion.push_back(recv_chunk);
32973 const unsigned recv_num_vertices = flat_package_unsigned_recv[
i + 2];
32974 recv_number_vertices_non_deletion.push_back(recv_num_vertices);
32979 for (
unsigned h = 0; h < recv_num_vertices; h++)
32982 tmp_vertex[0] = flat_package_double_recv[j++];
32983 tmp_vertex[1] = flat_package_double_recv[j++];
32985 temp_recv_vertices.push_back(tmp_vertex);
32989 recv_vertices_for_non_deletion.push_back(temp_recv_vertices);
33004 const unsigned n_recv_shd_bnd_id_for_non_deletion =
33005 recv_shd_bnd_id_for_non_deletion.size();
33008 for (
unsigned i = 0;
i < n_recv_shd_bnd_id_for_non_deletion;
i++)
33011 const unsigned shd_bnd_id = recv_shd_bnd_id_for_non_deletion[
i];
33013 unsigned chunk = recv_chunk_for_non_deletion[
i];
33020 const unsigned n_vertices = recv_number_vertices_non_deletion[
i];
33022 for (
unsigned h = 0; h < n_vertices; h++)
33026 vertex[0] = recv_vertices_for_non_deletion[
i][h][0];
33027 vertex[1] = recv_vertices_for_non_deletion[
i][h][1];
33032 Boundary_connections_pt[shd_bnd_id].insert(vertex);
33049 template<
class ELEMENT>
33059 dummy_resume_initial_connection_polyline_pt.clear();
33060 dummy_resume_final_connection_polyline_pt.clear();
33064 const unsigned init_shd_bnd_id = this->initial_shared_boundary_id();
33082 const unsigned n_outer_boundaries = tmp_outer_polygons_pt.size();
33085 for (
unsigned i = 0;
i < n_outer_boundaries;
i++)
33091 const unsigned n_polyline = tmp_polygon_pt->
npolyline();
33093 for (
unsigned p = 0; p < n_polyline; p++)
33099 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
33102 if (bnd_id < init_shd_bnd_id)
33105 restore_polyline_connections_helper(
33107 dummy_resume_initial_connection_polyline_pt,
33108 dummy_resume_final_connection_polyline_pt);
33125 const unsigned n_open_boundaries = tmp_open_curves_pt.size();
33128 for (
unsigned i = 0;
i < n_open_boundaries;
i++)
33135 const unsigned n_curve_section = tmp_open_curve_pt->
ncurve_section();
33138 for (
unsigned p = 0; p < n_curve_section; p++)
33146 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
33149 if (bnd_id < init_shd_bnd_id)
33152 restore_polyline_connections_helper(
33154 dummy_resume_initial_connection_polyline_pt,
33155 dummy_resume_final_connection_polyline_pt);
33174 template<
class ELEMENT>
33180 resume_initial_connection_polyline_pt.clear();
33181 resume_final_connection_polyline_pt.clear();
33192 const unsigned n_outer_boundaries = this->Outer_boundary_pt.size();
33195 for (
unsigned i = 0;
i < n_outer_boundaries;
i++)
33201 const unsigned n_polyline = tmp_polygon_pt->
npolyline();
33203 for (
unsigned p = 0; p < n_polyline; p++)
33209 restore_polyline_connections_helper(
33211 resume_initial_connection_polyline_pt,
33212 resume_final_connection_polyline_pt);
33223 const unsigned n_internal_boundaries = this->Internal_polygon_pt.size();
33226 for (
unsigned i = 0;
i < n_internal_boundaries;
i++)
33232 const unsigned n_polyline = tmp_polygon_pt->
npolyline();
33234 for (
unsigned p = 0; p < n_polyline; p++)
33240 restore_polyline_connections_helper(
33242 resume_initial_connection_polyline_pt,
33243 resume_final_connection_polyline_pt);
33254 const unsigned n_open_boundaries = this->Internal_open_curve_pt.size();
33257 for (
unsigned i = 0;
i < n_open_boundaries;
i++)
33261 this->Internal_open_curve_pt[
i];
33265 const unsigned n_curve_section = tmp_open_curve_pt->
ncurve_section();
33268 for (
unsigned p = 0; p < n_curve_section; p++)
33276 restore_polyline_connections_helper(
33278 resume_initial_connection_polyline_pt,
33279 resume_final_connection_polyline_pt);
33294 template<
class ELEMENT>
33311 const unsigned dst_bnd_id_initial =
33320#ifdef OOMPH_HAS_MPI
33321 if (this->is_mesh_distributed())
33324 const unsigned init_shd_bnd_id = this->initial_shared_boundary_id();
33326 if (dst_bnd_id_initial >= init_shd_bnd_id)
33329 const unsigned bnd_id = polyline_pt->
boundary_id();
33330 std::ostringstream error_message;
33332 <<
"INITIAL VERTEX CONNECTION\n"
33333 <<
"The current original boundary is trying to connect to a\n"
33334 <<
"shared boundary, this is not allowed. In this case the\n"
33335 <<
"shared boundary should be the one that connects with the\n"
33336 <<
"original boundary\n"
33337 <<
"The current original boundary (" << bnd_id <<
") is marked\n"
33338 <<
"to have a connection at the\nINITIAL vertex ("
33339 << src_vertex_coordinates_initial[0] <<
","
33340 << src_vertex_coordinates_initial[1] <<
")\n"
33341 <<
"with the shared boundary (" << dst_bnd_id_initial <<
")\n"
33342 <<
"This is the list of vertices on the shared destination "
33347 this->boundary_polyline_pt(dst_bnd_id_initial);
33349 const unsigned n_vertex_dst_boundary = dst_polyline->
nvertex();
33351 for (
unsigned i = 0;
i < n_vertex_dst_boundary;
i++)
33354 error_message <<
"Vertex#(i): (" << current_vertex[0] <<
", "
33355 << current_vertex[1] <<
")\n";
33358 error_message.str(),
33359 "RefineableTriangleMesh::restore_polyline_connections_helper()",
33360 OOMPH_EXCEPTION_LOCATION);
33370 bool found_vertex_on_dst_boundary_initial =
false;
33374 unsigned sub_poly_to_connect = 0;
33377 unsigned n_vertex_connection_initial = 0;
33382 bool connecting_to_an_split_boundary =
false;
33386 bool connecting_to_an_overlaped_boundary =
false;
33388#ifdef OOMPH_HAS_MPI
33389 if (this->is_mesh_distributed())
33394 if (this->boundary_was_splitted(dst_bnd_id_initial))
33396 connecting_to_an_split_boundary =
true;
33405 if (connecting_to_an_split_boundary)
33409 const unsigned n_sub_poly =
33410 this->nboundary_subpolylines(dst_bnd_id_initial);
33414 for (
unsigned ii = 0; ii < n_sub_poly; ii++)
33416 if (this->boundary_marked_as_shared_boundary(dst_bnd_id_initial,
33421 connecting_to_an_overlaped_boundary =
true;
33432 if (this->boundary_marked_as_shared_boundary(dst_bnd_id_initial, 0))
33435 connecting_to_an_overlaped_boundary =
true;
33446 if (!(connecting_to_an_split_boundary ||
33447 connecting_to_an_overlaped_boundary))
33451 poly_to_connect_pt = this->boundary_polyline_pt(dst_bnd_id_initial);
33461 if (!connecting_to_an_split_boundary)
33465 if (!connecting_to_an_overlaped_boundary)
33469 found_vertex_on_dst_boundary_initial =
33470 this->get_connected_vertex_number_on_destination_polyline(
33471 poly_to_connect_pt,
33472 src_vertex_coordinates_initial,
33473 n_vertex_connection_initial);
33486#ifdef OOMPH_HAS_MPI
33494 this->boundary_subpolylines(dst_bnd_id_initial);
33497 const unsigned nsub_poly = tmp_vector_subpolylines.size();
33499 if (nsub_poly <= 1)
33501 std::ostringstream error_message;
33502 error_message <<
"The boundary (" << dst_bnd_id_initial <<
") was "
33503 <<
"marked to be splitted but\n"
33504 <<
"there are only (" << nsub_poly <<
") polylines to "
33505 <<
"represent it.\n";
33507 error_message.str(),
33508 "RefineableTriangleMesh::restore_polyline_connections_helper()",
33509 OOMPH_EXCEPTION_LOCATION);
33520 if (!connecting_to_an_overlaped_boundary)
33528 for (
unsigned isub = 0; isub < nsub_poly; isub++)
33531 poly_to_connect_pt = tmp_vector_subpolylines[isub];
33533 found_vertex_on_dst_boundary_initial =
33534 this->get_connected_vertex_number_on_destination_polyline(
33535 poly_to_connect_pt,
33536 src_vertex_coordinates_initial,
33537 n_vertex_connection_initial);
33541 if (found_vertex_on_dst_boundary_initial)
33545 sub_poly_to_connect = isub;
33561 for (
unsigned isub = 0; isub < nsub_poly; isub++)
33565 if (!this->boundary_marked_as_shared_boundary(dst_bnd_id_initial,
33569 poly_to_connect_pt = tmp_vector_subpolylines[isub];
33572 found_vertex_on_dst_boundary_initial =
33573 this->get_connected_vertex_number_on_destination_polyline(
33574 poly_to_connect_pt,
33575 src_vertex_coordinates_initial,
33576 n_vertex_connection_initial);
33579 if (found_vertex_on_dst_boundary_initial)
33583 sub_poly_to_connect = isub;
33598 if (!found_vertex_on_dst_boundary_initial)
33601#ifdef OOMPH_HAS_MPI
33602 if (this->is_mesh_distributed())
33612 resume_initial_connection_polyline_pt.push_back(polyline_pt);
33624 const unsigned bnd_id = polyline_pt->
boundary_id();
33625 std::ostringstream error_message;
33627 <<
"INITIAL VERTEX CONNECTION\n"
33628 <<
"It was not possible to find the associated "
33629 <<
"vertex number on the destination boundary\n"
33630 <<
"The current boundary (" << bnd_id <<
") is marked to have"
33631 <<
"a connection at the\nINITIAL vertex ("
33632 << src_vertex_coordinates_initial[0] <<
","
33633 << src_vertex_coordinates_initial[1] <<
")\n"
33634 <<
"with boundary (" << dst_bnd_id_initial <<
")\n"
33635 <<
"This is the list of vertices on the destination boundary\n";
33639 this->boundary_polyline_pt(dst_bnd_id_initial);
33641 const unsigned n_vertex_dst_boundary = dst_polyline->
nvertex();
33643 for (
unsigned i = 0;
i < n_vertex_dst_boundary;
i++)
33646 error_message <<
"Vertex#(i): (" << current_vertex[0] <<
", "
33647 << current_vertex[1] <<
")\n";
33650 error_message.str(),
33651 "RefineableTriangleMesh::restore_polyline_connections_helper()",
33652 OOMPH_EXCEPTION_LOCATION);
33662 n_vertex_connection_initial;
33679 const unsigned dst_bnd_id_final =
33683 const unsigned tmp_n_vertices = polyline_pt->
nvertex();
33690#ifdef OOMPH_HAS_MPI
33691 if (this->is_mesh_distributed())
33694 const unsigned init_shd_bnd_id = this->initial_shared_boundary_id();
33696 if (dst_bnd_id_final >= init_shd_bnd_id)
33699 const unsigned bnd_id = polyline_pt->
boundary_id();
33700 std::ostringstream error_message;
33702 <<
"FINAL VERTEX CONNECTION\n"
33703 <<
"The current original boundary is trying to connect to a\n"
33704 <<
"shared boundary, this is not allowed. In this case the\n"
33705 <<
"shared boundary should be the one that connects with the\n"
33706 <<
"original boundary\n"
33707 <<
"The current boundary (" << bnd_id <<
") is marked to have "
33708 <<
"a connection at the\nFINAL vertex ("
33709 << src_vertex_coordinates_final[0] <<
","
33710 << src_vertex_coordinates_final[1] <<
")\n"
33711 <<
"with boundary (" << dst_bnd_id_final <<
")\n"
33712 <<
"This is the list of vertices on the destination boundary\n";
33716 this->boundary_polyline_pt(dst_bnd_id_final);
33718 const unsigned n_vertex_dst_boundary = dst_polyline->
nvertex();
33720 for (
unsigned i = 0;
i < n_vertex_dst_boundary;
i++)
33723 error_message <<
"Vertex#(" <<
i <<
"): (" << current_vertex[0]
33724 <<
", " << current_vertex[1] <<
")\n";
33727 error_message.str(),
33728 "RefineableTriangleMesh::restore_polyline_connections_helper()",
33729 OOMPH_EXCEPTION_LOCATION);
33739 bool found_vertex_on_dst_boundary_final =
false;
33743 unsigned sub_poly_to_connect = 0;
33746 unsigned n_vertex_connection_final = 0;
33751 bool connecting_to_an_split_boundary =
false;
33755 bool connecting_to_an_overlaped_boundary =
false;
33757#ifdef OOMPH_HAS_MPI
33758 if (this->is_mesh_distributed())
33763 if (this->boundary_was_splitted(dst_bnd_id_final))
33765 connecting_to_an_split_boundary =
true;
33774 if (connecting_to_an_split_boundary)
33778 const unsigned n_sub_poly =
33779 this->nboundary_subpolylines(dst_bnd_id_final);
33783 for (
unsigned ii = 0; ii < n_sub_poly; ii++)
33785 if (this->boundary_marked_as_shared_boundary(dst_bnd_id_final, ii))
33789 connecting_to_an_overlaped_boundary =
true;
33800 if (this->boundary_marked_as_shared_boundary(dst_bnd_id_final, 0))
33803 connecting_to_an_overlaped_boundary =
true;
33814 if (!(connecting_to_an_split_boundary ||
33815 connecting_to_an_overlaped_boundary))
33819 poly_to_connect_pt = this->boundary_polyline_pt(dst_bnd_id_final);
33829 if (!connecting_to_an_split_boundary)
33833 if (!connecting_to_an_overlaped_boundary)
33837 found_vertex_on_dst_boundary_final =
33838 this->get_connected_vertex_number_on_destination_polyline(
33839 poly_to_connect_pt,
33840 src_vertex_coordinates_final,
33841 n_vertex_connection_final);
33854#ifdef OOMPH_HAS_MPI
33862 this->boundary_subpolylines(dst_bnd_id_final);
33865 const unsigned nsub_poly = tmp_vector_subpolylines.size();
33867 if (nsub_poly <= 1)
33869 std::ostringstream error_message;
33870 error_message <<
"The boundary (" << dst_bnd_id_final <<
") was "
33871 <<
"marked to be splitted but\n"
33872 <<
"there are only (" << nsub_poly <<
") polylines to "
33873 <<
"represent it.\n";
33875 error_message.str(),
33876 "RefineableTriangleMesh::restore_polyline_connections_helper()",
33877 OOMPH_EXCEPTION_LOCATION);
33888 if (!connecting_to_an_overlaped_boundary)
33896 for (
unsigned isub = 0; isub < nsub_poly; isub++)
33899 poly_to_connect_pt = tmp_vector_subpolylines[isub];
33901 found_vertex_on_dst_boundary_final =
33902 this->get_connected_vertex_number_on_destination_polyline(
33903 poly_to_connect_pt,
33904 src_vertex_coordinates_final,
33905 n_vertex_connection_final);
33909 if (found_vertex_on_dst_boundary_final)
33913 sub_poly_to_connect = isub;
33929 for (
unsigned isub = 0; isub < nsub_poly; isub++)
33933 if (!this->boundary_marked_as_shared_boundary(dst_bnd_id_final,
33937 poly_to_connect_pt = tmp_vector_subpolylines[isub];
33940 found_vertex_on_dst_boundary_final =
33941 this->get_connected_vertex_number_on_destination_polyline(
33942 poly_to_connect_pt,
33943 src_vertex_coordinates_final,
33944 n_vertex_connection_final);
33947 if (found_vertex_on_dst_boundary_final)
33951 sub_poly_to_connect = isub;
33966 if (!found_vertex_on_dst_boundary_final)
33969#ifdef OOMPH_HAS_MPI
33970 if (this->is_mesh_distributed())
33980 resume_final_connection_polyline_pt.push_back(polyline_pt);
33992 const unsigned bnd_id = polyline_pt->
boundary_id();
33993 std::ostringstream error_message;
33995 <<
"FINAL VERTEX CONNECTION\n"
33996 <<
"It was not possible to find the associated "
33997 <<
"vertex number on the destination boundary\n"
33998 <<
"The current boundary (" << bnd_id <<
") is marked to have "
33999 <<
"a connection at the\nFINAL vertex ("
34000 << src_vertex_coordinates_final[0] <<
","
34001 << src_vertex_coordinates_final[1] <<
")\n"
34002 <<
"with boundary (" << dst_bnd_id_final <<
")\n"
34003 <<
"This is the list of vertices on the destination boundary\n";
34007 this->boundary_polyline_pt(dst_bnd_id_final);
34009 const unsigned n_vertex_dst_boundary = dst_polyline->
nvertex();
34011 for (
unsigned i = 0;
i < n_vertex_dst_boundary;
i++)
34014 error_message <<
"Vertex#(" <<
i <<
"): (" << current_vertex[0]
34015 <<
", " << current_vertex[1] <<
")\n";
34018 error_message.str(),
34019 "RefineableTriangleMesh::restore_polyline_connections_helper()",
34020 OOMPH_EXCEPTION_LOCATION);
34029 n_vertex_connection_final;
34047 template<
class ELEMENT>
34054 const unsigned n_initial_poly =
34055 resume_initial_connection_polyline_pt.size();
34058 for (
unsigned p = 0; p < n_initial_poly; p++)
34062 resume_initial_connection_polyline_pt[p];
34069 const unsigned n_final_poly = resume_final_connection_polyline_pt.size();
34072 for (
unsigned p = 0; p < n_final_poly; p++)
34076 resume_final_connection_polyline_pt[p];
34082 resume_initial_connection_polyline_pt.clear();
34083 resume_final_connection_polyline_pt.clear();
34090 template<
class ELEMENT>
34094 const unsigned& dst_bnd_id,
34095 unsigned& vertex_number)
34097 bool found_associated_vertex_number =
false;
34102 const unsigned n_vertices = dst_polyline->
nvertex();
34106 for (
unsigned i = 0;
i < n_vertices;
i++)
34110 double error = (vertex_coordinates[0] - current_vertex[0]) *
34111 (vertex_coordinates[0] - current_vertex[0]) +
34112 (vertex_coordinates[1] - current_vertex[1]) *
34113 (vertex_coordinates[1] - current_vertex[1]);
34115 error = sqrt(error);
34120 found_associated_vertex_number =
true;
34125 return found_associated_vertex_number;
34137 template<
class ELEMENT>
34147 if (this->is_mesh_distributed() && !check_only)
34149 std::stringstream error_message;
34151 <<
"The updating of polygons of a distributed mesh can ONLY be\n"
34152 <<
"performed using the element's area associated to the halo(ed)\n"
34154 <<
"1) Make sure you have enabled the parallel mesh adaptation\n"
34155 <<
"option if you are working with a distributed mesh, OR\n"
34156 <<
"2) Make sure to call the update_..._using_elements_area() methods\n"
34157 <<
"if the mesh is marked as distributed\n\n";
34159 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
34165 bool unrefinement_was_performed =
false;
34166 bool refinement_was_performed =
false;
34167 bool max_length_applied =
false;
34170 const unsigned n_polyline = polygon_pt->
npolyline();
34176 get_face_mesh_representation(polygon_pt, face_mesh_pt);
34184 for (
unsigned p = 0; p < n_polyline; p++)
34189 std::set<Vector<double>> vertex_nodes;
34198 unsigned n_face_element = face_mesh_pt[p]->nelement();
34199 for (
unsigned e = 0;
e < n_face_element; ++
e)
34203#ifdef OOMPH_HAS_MPI
34205 if (this->is_mesh_distributed() && el_pt->
is_halo())
34211 unsigned n_node = el_pt->
nnode();
34216 el_pt->
node_pt(0)->get_coordinates_on_boundary(bound, bound_left);
34217 vertex_coord[0] = bound_left[0];
34220 for (
unsigned i = 0;
i < 2;
i++)
34222 vertex_coord[
i + 1] = el_pt->
node_pt(0)->x(
i);
34224 vertex_nodes.insert(vertex_coord);
34230 ->get_coordinates_on_boundary(bound, bound_right);
34231 vertex_coord[0] = bound_right[0];
34234 for (
unsigned i = 0;
i < 2;
i++)
34236 vertex_coord[
i + 1] = el_pt->
node_pt(n_node - 1)->x(
i);
34238 vertex_nodes.insert(vertex_coord);
34242 unsigned n_poly_vertex = vertex_nodes.size();
34244 unsigned count = 0;
34245 for (std::set<
Vector<double>>::iterator it = vertex_nodes.begin();
34246 it != vertex_nodes.end();
34249 tmp_vector_vertex_node[count].resize(3);
34250 tmp_vector_vertex_node[count][0] = (*it)[0];
34251 tmp_vector_vertex_node[count][1] = (*it)[1];
34252 tmp_vector_vertex_node[count][2] = (*it)[2];
34257 unsigned n_vertex = tmp_vector_vertex_node.size();
34261 double unrefinement_tolerance =
34267 if (unrefinement_tolerance > 0.0 && n_vertex >= 3)
34269 unrefinement_was_performed = unrefine_boundary(bound,
34271 tmp_vector_vertex_node,
34272 unrefinement_tolerance,
34278 if (check_only && unrefinement_was_performed)
34282 for (
unsigned p = 0; p < n_polyline; p++)
34284 face_mesh_pt[p]->flush_node_storage();
34285 delete face_mesh_pt[p];
34294 n_vertex = tmp_vector_vertex_node.size();
34299 double refinement_tolerance =
34301 if (refinement_tolerance > 0.0 && n_vertex >= 2)
34303 refinement_was_performed = refine_boundary(face_mesh_pt[p],
34304 tmp_vector_vertex_node,
34305 refinement_tolerance,
34311 if (check_only && refinement_was_performed)
34315 for (
unsigned p = 0; p < n_polyline; p++)
34317 face_mesh_pt[p]->flush_node_storage();
34318 delete face_mesh_pt[p];
34328 n_vertex = tmp_vector_vertex_node.size();
34334 if (maximum_length > 0.0 && n_vertex >= 2)
34336 max_length_applied = apply_max_length_constraint(
34337 face_mesh_pt[p], tmp_vector_vertex_node, maximum_length);
34341 if (check_only && max_length_applied)
34345 for (
unsigned p = 0; p < n_polyline; p++)
34347 face_mesh_pt[p]->flush_node_storage();
34348 delete face_mesh_pt[p];
34356 n_vertex = tmp_vector_vertex_node.size();
34359 for (
unsigned i = 0;
i < n_vertex;
i++)
34361 vector_vertex_node[
i].resize(2);
34362 vector_vertex_node[
i][0] = tmp_vector_vertex_node[
i][1];
34363 vector_vertex_node[
i][1] = tmp_vector_vertex_node[
i][2];
34366#ifdef OOMPH_HAS_MPI
34370 if (!this->is_mesh_distributed())
34373 if ((p > 0) && !check_only)
34377 unsigned n_prev_vertex =
34379 final_vertex_of_previous_segment =
34383 unsigned prev_seg_boundary_id =
34388 double error = 0.0;
34389 for (
unsigned i = 0;
i < 2;
i++)
34391 const double dist = final_vertex_of_previous_segment[
i] -
34392 (*vector_vertex_node.begin())[
i];
34393 error += dist * dist;
34395 error = sqrt(error);
34403 double rev_error = 0.0;
34404 for (
unsigned i = 0;
i < 2;
i++)
34406 const double dist = final_vertex_of_previous_segment[
i] -
34407 (*--vector_vertex_node.end())[
i];
34408 rev_error += dist * dist;
34410 rev_error = sqrt(rev_error);
34424 initial_vertex_of_previous_segment =
34427 unsigned prev_seg_boundary_id =
34432 double error = 0.0;
34433 for (
unsigned i = 0;
i < 2;
i++)
34435 const double dist = initial_vertex_of_previous_segment[
i] -
34436 (*vector_vertex_node.begin())[
i];
34437 error += dist * dist;
34439 error = sqrt(error);
34448 double rev_error = 0.0;
34449 for (
unsigned i = 0;
i < 2;
i++)
34451 const double dist = initial_vertex_of_previous_segment[
i] -
34452 (*--vector_vertex_node.end())[
i];
34453 rev_error += dist * dist;
34462 std::ostringstream error_stream;
34464 <<
"The distance between the first node of the current\n"
34465 <<
"line segment (boundary " << bound
34466 <<
") and either end of "
34467 <<
"the previous line segment\n"
34468 <<
"(boundary " << prev_seg_boundary_id
34469 <<
") is bigger than "
34470 <<
"the desired tolerance "
34473 <<
"This suggests that the polylines defining the "
34475 <<
"representation are not properly ordered.\n"
34476 <<
"Fail on last vertex of polyline: ("
34477 << prev_seg_boundary_id
34478 <<
") and\nfirst vertex of polyline (" << bound
34479 <<
").\nThis should have failed when first trying to "
34480 <<
"construct the\npolygon.\n";
34482 OOMPH_CURRENT_FUNCTION,
34483 OOMPH_EXCEPTION_LOCATION);
34490 std::reverse(vector_vertex_node.begin(),
34491 vector_vertex_node.end());
34505 std::ostringstream error_stream;
34507 <<
"The distance between the first node of the current\n"
34508 <<
"line segment (boundary " << bound
34509 <<
") and either end of "
34510 <<
"the previous line segment\n"
34511 <<
"(boundary " << prev_seg_boundary_id
34512 <<
") is bigger than the "
34513 <<
"desired tolerance "
34516 <<
"This suggests that the polylines defining the polygonal\n"
34517 <<
"representation are not properly ordered.\n"
34518 <<
"Fail on last vertex of polyline: ("
34519 << prev_seg_boundary_id <<
") and\nfirst vertex of polyline ("
34521 <<
"This should have failed when first trying to construct "
34525 OOMPH_CURRENT_FUNCTION,
34526 OOMPH_EXCEPTION_LOCATION);
34532 std::reverse(vector_vertex_node.begin(),
34533 vector_vertex_node.end());
34560 this->copy_connection_information(polygon_pt->
polyline_pt(p),
34561 tmp_curve_section_pt);
34566 bool delete_it_on_destructor =
false;
34568 std::set<TriangleMeshCurveSection*>::iterator it =
34571 if (it != this->Free_curve_section_pt.end())
34573 this->Free_curve_section_pt.erase(it);
34575 delete_it_on_destructor =
true;
34583 this->Boundary_curve_section_pt[bound] =
34586 if (delete_it_on_destructor)
34597 for (
unsigned p = 0; p < n_polyline; p++)
34599 face_mesh_pt[p]->flush_node_storage();
34600 delete face_mesh_pt[p];
34614 return (unrefinement_was_performed || refinement_was_performed ||
34615 max_length_applied);
34628 template<
class ELEMENT>
34638 if (this->is_mesh_distributed() && !check_only)
34640 std::stringstream error_message;
34642 <<
"The updating of open curves of a distributed mesh can ONLY be\n"
34643 <<
"performed using the element's area associated to the halo(ed)\n"
34645 <<
"1) Make sure you have enabled the parallel mesh adaptation\n"
34646 <<
"option if you are working with a distributed mesh, OR\n"
34647 <<
"2) Make sure to call the update_..._using_elements_area() methods\n"
34648 <<
"if the mesh is marked as distributed\n\n";
34650 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
34656 bool unrefinement_was_performed =
false;
34657 bool refinement_was_performed =
false;
34658 bool max_length_applied =
false;
34667 get_face_mesh_representation(open_polyline_pt, face_mesh_pt);
34675 for (
unsigned p = 0; p < n_polyline; p++)
34680 std::set<Vector<double>> vertex_nodes;
34683 const unsigned bound =
34687 const unsigned chunk =
34691 unsigned n_face_element = face_mesh_pt[p]->nelement();
34694 for (
unsigned e = 0;
e < n_face_element; ++
e)
34697 unsigned n_node = el_pt->
nnode();
34702 el_pt->
node_pt(0)->get_coordinates_on_boundary(bound, bound_left);
34703 vertex_coord[0] = bound_left[0];
34706 for (
unsigned i = 0;
i < 2;
i++)
34708 vertex_coord[
i + 1] = el_pt->
node_pt(0)->x(
i);
34710 vertex_nodes.insert(vertex_coord);
34716 ->get_coordinates_on_boundary(bound, bound_right);
34717 vertex_coord[0] = bound_right[0];
34720 for (
unsigned i = 0;
i < 2;
i++)
34722 vertex_coord[
i + 1] = el_pt->
node_pt(n_node - 1)->x(
i);
34724 vertex_nodes.insert(vertex_coord);
34728 unsigned n_poly_vertex = vertex_nodes.size();
34730 unsigned count = 0;
34731 for (std::set<
Vector<double>>::iterator it = vertex_nodes.begin();
34732 it != vertex_nodes.end();
34735 tmp_vector_vertex_node[count].resize(3);
34736 tmp_vector_vertex_node[count][0] = (*it)[0];
34737 tmp_vector_vertex_node[count][1] = (*it)[1];
34738 tmp_vector_vertex_node[count][2] = (*it)[2];
34743 unsigned n_vertex = tmp_vector_vertex_node.size();
34747 double unrefinement_tolerance =
34753 if (unrefinement_tolerance > 0.0 && n_vertex >= 3)
34755 unrefinement_was_performed = unrefine_boundary(bound,
34757 tmp_vector_vertex_node,
34758 unrefinement_tolerance,
34764 if (check_only && unrefinement_was_performed)
34768 for (
unsigned p = 0; p < n_polyline; p++)
34770 face_mesh_pt[p]->flush_node_storage();
34771 delete face_mesh_pt[p];
34781 n_vertex = tmp_vector_vertex_node.size();
34786 double refinement_tolerance =
34788 if (refinement_tolerance > 0.0 && n_vertex >= 2)
34790 refinement_was_performed = refine_boundary(face_mesh_pt[p],
34791 tmp_vector_vertex_node,
34792 refinement_tolerance,
34798 if (check_only && refinement_was_performed)
34802 for (
unsigned p = 0; p < n_polyline; p++)
34804 face_mesh_pt[p]->flush_node_storage();
34805 delete face_mesh_pt[p];
34815 n_vertex = tmp_vector_vertex_node.size();
34820 double maximum_length =
34822 if (maximum_length > 0.0 && n_vertex >= 2)
34824 bool max_length_applied =
false;
34825 max_length_applied = apply_max_length_constraint(
34826 face_mesh_pt[p], tmp_vector_vertex_node, maximum_length);
34830 if (check_only && max_length_applied)
34834 for (
unsigned p = 0; p < n_polyline; p++)
34836 face_mesh_pt[p]->flush_node_storage();
34837 delete face_mesh_pt[p];
34845 n_vertex = tmp_vector_vertex_node.size();
34848 for (
unsigned i = 0;
i < n_vertex;
i++)
34850 vector_vertex_node[
i].resize(2);
34851 vector_vertex_node[
i][0] = tmp_vector_vertex_node[
i][1];
34852 vector_vertex_node[
i][1] = tmp_vector_vertex_node[
i][2];
34855#ifdef OOMPH_HAS_MPI
34859 if (!this->is_mesh_distributed())
34868 if ((p > 0) && !check_only)
34873 final_vertex_of_previous_segment);
34875 unsigned prev_seg_boundary_id =
34880 double error = 0.0;
34881 for (
unsigned i = 0;
i < 2;
i++)
34883 const double dist = final_vertex_of_previous_segment[
i] -
34884 (*vector_vertex_node.begin())[
i];
34885 error += dist * dist;
34887 error = sqrt(error);
34896 for (
unsigned i = 0;
i < 2;
i++)
34898 const double dist = final_vertex_of_previous_segment[
i] -
34899 (*--vector_vertex_node.end())[
i];
34900 error += dist * dist;
34902 error = sqrt(error);
34917 initial_vertex_of_previous_segment);
34922 for (
unsigned i = 0;
i < 2;
i++)
34924 const double dist = initial_vertex_of_previous_segment[
i] -
34925 (*vector_vertex_node.begin())[
i];
34926 error += dist * dist;
34928 error = sqrt(error);
34938 for (
unsigned i = 0;
i < 2;
i++)
34940 const double dist = initial_vertex_of_previous_segment[
i] -
34941 (*--vector_vertex_node.end())[
i];
34942 error += dist * dist;
34944 error = sqrt(error);
34949 std::ostringstream error_stream;
34951 <<
"The distance between the first node of the current\n"
34952 <<
"line segment (boundary " << bound
34953 <<
") and either end of the previous line segment\n"
34954 <<
"(boundary " << prev_seg_boundary_id
34955 <<
") is bigger than "
34956 <<
"the desired tolerance "
34959 <<
"This suggests that the polylines defining the open "
34961 <<
"representation are not properly ordered.\n"
34962 <<
"Fail on last vertex of polyline: ("
34963 << prev_seg_boundary_id
34964 <<
") and\nfirst vertex of polyline (" << bound <<
").\n"
34965 <<
"This should have failed when first trying to "
34967 <<
"the open curve.\n";
34969 OOMPH_CURRENT_FUNCTION,
34970 OOMPH_EXCEPTION_LOCATION);
34977 std::reverse(vector_vertex_node.begin(),
34978 vector_vertex_node.end());
34989 std::ostringstream error_stream;
34991 <<
"The distance between the first node of the current\n"
34992 <<
"line segment (boundary " << bound
34993 <<
") and either end of "
34994 <<
"the previous line segment\n"
34995 <<
"(boundary " << prev_seg_boundary_id
34996 <<
") is bigger than the "
34997 <<
"desired tolerance "
35000 <<
"This suggests that the polylines defining the polygonal\n"
35001 <<
"representation are not properly ordered.\n"
35002 <<
"Fail on last vertex of polyline: ("
35003 << prev_seg_boundary_id <<
") and\nfirst vertex of polyline ("
35005 <<
"This should have failed when first trying to construct "
35009 OOMPH_CURRENT_FUNCTION,
35010 OOMPH_EXCEPTION_LOCATION);
35016 std::reverse(vector_vertex_node.begin(),
35017 vector_vertex_node.end());
35045 this->copy_connection_information(open_polyline_pt->
polyline_pt(p),
35046 tmp_curve_section);
35048 std::set<TriangleMeshCurveSection*>::iterator it =
35049 this->Free_curve_section_pt.find(
35052 bool delete_it_on_destructor =
false;
35054 if (it != this->Free_curve_section_pt.end())
35057 this->Free_curve_section_pt.erase(it);
35059 delete_it_on_destructor =
true;
35067 this->Boundary_curve_section_pt[bound] =
35070 if (delete_it_on_destructor)
35072 this->Free_curve_section_pt.insert(
35082 for (
unsigned p = 0; p < n_polyline; p++)
35084 face_mesh_pt[p]->flush_node_storage();
35085 delete face_mesh_pt[p];
35099 return (unrefinement_was_performed || refinement_was_performed ||
35100 max_length_applied);
35112 template<
class ELEMENT>
35117 double& unrefinement_tolerance,
35118 const bool& check_only)
35121 std::set<Vector<double>> no_delete_vertex;
35124 const bool boundary_receive_connections =
35125 this->boundary_connections(b, c, no_delete_vertex);
35129 bool unrefinement_was_performed =
false;
35131 unsigned n_vertex = vector_bnd_vertices.size();
35135 unsigned counter = 1;
35141 for (
unsigned i = 1;
i <= n_vertex - 2;
i += 2)
35144 double a_x = vector_bnd_vertices[
i - 1][1];
35145 double a_y = vector_bnd_vertices[
i - 1][2];
35146 double b_x = vector_bnd_vertices[
i][1];
35147 double b_y = vector_bnd_vertices[
i][2];
35148 double c_x = vector_bnd_vertices[
i + 1][1];
35149 double c_y = vector_bnd_vertices[
i + 1][2];
35151 double a = b_x - a_x;
35152 double b = b_y - a_y;
35153 double c = c_x - a_x;
35154 double d = c_y - a_y;
35156 double e = a * (a_x + b_x) + b * (a_y + b_y);
35157 double f = c * (a_x + c_x) + d * (a_y + c_y);
35159 double g = 2.0 * (a * (c_y - b_y) - b * (c_x - b_x));
35161 bool do_it =
false;
35162 if (std::fabs(g) < 1.0e-14)
35172 double p_x = (d *
e - b *
f) / g;
35173 double p_y = (a *
f - c *
e) / g;
35175 double r = sqrt(pow((a_x - p_x), 2) + pow((a_y - p_y), 2));
35177 double rhalfca_x = 0.5 * (a_x - c_x);
35178 double rhalfca_y = 0.5 * (a_y - c_y);
35180 double halfca_squared = pow(rhalfca_x, 2) + pow(rhalfca_y, 2);
35182 double sticky_out_bit = r - sqrt(std::fabs((r * r) - halfca_squared));
35187 if ((sticky_out_bit / (2.0 * sqrt(halfca_squared))) <
35188 unrefinement_tolerance)
35200 if (do_it && boundary_receive_connections)
35203 for (std::set<
Vector<double>>::iterator it = no_delete_vertex.begin();
35204 it != no_delete_vertex.end();
35209 const double x = (*it)[0];
35210 const double y = (*it)[1];
35211 double error = (b_x -
x) * (b_x -
x) + (b_y - y) * (b_y - y);
35212 error = sqrt(error);
35227 vector_bnd_vertices[
i].resize(0);
35246 if ((counter) == (n_vertex - 1))
35249 unsigned i = vector_bnd_vertices.size() - 2;
35255 if (vector_bnd_vertices[counter - 2].size() != 0)
35274 double a_x = vector_bnd_vertices[n][1];
35275 double a_y = vector_bnd_vertices[n][2];
35276 double b_x = vector_bnd_vertices[
i][1];
35277 double b_y = vector_bnd_vertices[
i][2];
35278 double c_x = vector_bnd_vertices[
i + 1][1];
35279 double c_y = vector_bnd_vertices[
i + 1][2];
35281 double a = b_x - a_x;
35282 double b = b_y - a_y;
35283 double c = c_x - a_x;
35284 double d = c_y - a_y;
35286 double e = a * (a_x + b_x) + b * (a_y + b_y);
35287 double f = c * (a_x + c_x) + d * (a_y + c_y);
35289 double g = 2.0 * (a * (c_y - b_y) - b * (c_x - b_x));
35291 bool do_it =
false;
35292 if (std::fabs(g) < 1.0e-14)
35302 double p_x = (d *
e - b *
f) / g;
35303 double p_y = (a *
f - c *
e) / g;
35305 double r = sqrt(pow((a_x - p_x), 2) + pow((a_y - p_y), 2));
35307 double rhalfca_x = 0.5 * (a_x - c_x);
35308 double rhalfca_y = 0.5 * (a_y - c_y);
35310 double halfca_squared = pow(rhalfca_x, 2) + pow(rhalfca_y, 2);
35312 double sticky_out_bit = r - sqrt(std::fabs((r * r) - halfca_squared));
35317 if ((sticky_out_bit / (2.0 * sqrt(halfca_squared))) <
35318 unrefinement_tolerance)
35330 if (do_it && boundary_receive_connections)
35333 for (std::set<
Vector<double>>::iterator it = no_delete_vertex.begin();
35334 it != no_delete_vertex.end();
35339 const double x = (*it)[0];
35340 const double y = (*it)[1];
35341 double error = (b_x -
x) * (b_x -
x) + (b_y - y) * (b_y - y);
35342 error = sqrt(error);
35357 vector_bnd_vertices[
i].resize(0);
35364 compact_vector.reserve(n_vertex);
35365 for (
unsigned i = 0;
i < n_vertex;
i++)
35368 if (vector_bnd_vertices[
i].size() != 0)
35370 compact_vector.push_back(vector_bnd_vertices[
i]);
35375 n_vertex = compact_vector.size();
35381 if (n_vertex != vector_bnd_vertices.size())
35383 unrefinement_was_performed =
true;
35387 vector_bnd_vertices.resize(n_vertex);
35388 for (
unsigned i = 0;
i < n_vertex;
i++)
35390 vector_bnd_vertices[
i].resize(3);
35391 vector_bnd_vertices[
i][0] = compact_vector[
i][0];
35392 vector_bnd_vertices[
i][1] = compact_vector[
i][1];
35393 vector_bnd_vertices[
i][2] = compact_vector[
i][2];
35396 return unrefinement_was_performed;
35407 template<
class ELEMENT>
35409 Mesh* face_mesh_pt,
35411 double& refinement_tolerance,
35412 const bool& check_only)
35416 bool refinement_was_performed =
false;
35423 unsigned n_vertex = vector_bnd_vertices.size();
35431 extended_vector.reserve(2 * n_vertex);
35434 for (
unsigned inod = 0; inod < n_vertex - 1; inod++)
35437 double zeta_left = vector_bnd_vertices[inod][0];
35441 for (
unsigned i = 0;
i < 2;
i++)
35443 R_left[
i] = vector_bnd_vertices[inod][
i + 1];
35447 double zeta_right = vector_bnd_vertices[inod + 1][0];
35451 for (
unsigned i = 0;
i < 2;
i++)
35453 R_right[
i] = vector_bnd_vertices[inod + 1][
i + 1];
35458 zeta_mid[0] = 0.5 * (zeta_left + zeta_right);
35463 mesh_geom_obj_pt->
position(zeta_mid, R_mid);
35468 for (
unsigned i = 0;
i < 2;
i++)
35470 R_mid_polygon[
i] = 0.5 * (R_right[
i] + R_left[
i]);
35476 sqrt((R_mid[0] - R_mid_polygon[0]) * (R_mid[0] - R_mid_polygon[0]) +
35477 (R_mid[1] - R_mid_polygon[1]) * (R_mid[1] - R_mid_polygon[1]));
35480 double length = sqrt((R_right[0] - R_left[0]) * (R_right[0] - R_left[0]) +
35481 (R_right[1] - R_left[1]) * (R_right[1] - R_left[1]));
35487 if ((distance / length) > refinement_tolerance)
35493 delete mesh_geom_obj_pt;
35498 new_node[0] = zeta_mid[0];
35499 new_node[1] = R_mid[0];
35500 new_node[2] = R_mid[1];
35503 extended_vector.push_back(vector_bnd_vertices[inod]);
35506 extended_vector.push_back(new_node);
35512 extended_vector.push_back(vector_bnd_vertices[inod]);
35517 extended_vector.push_back(vector_bnd_vertices[n_vertex - 1]);
35520 n_vertex = extended_vector.size();
35525 if (n_vertex != vector_bnd_vertices.size())
35527 refinement_was_performed =
true;
35531 vector_bnd_vertices.resize(n_vertex);
35532 for (
unsigned i = 0;
i < n_vertex;
i++)
35534 vector_bnd_vertices[
i].resize(3);
35535 vector_bnd_vertices[
i][0] = extended_vector[
i][0];
35536 vector_bnd_vertices[
i][1] = extended_vector[
i][1];
35537 vector_bnd_vertices[
i][2] = extended_vector[
i][2];
35542 delete mesh_geom_obj_pt;
35544 return refinement_was_performed;
35553 template<
class ELEMENT>
35555 Mesh* face_mesh_pt,
35557 double& max_length_constraint)
35561 bool max_length_applied =
false;
35568 unsigned n_vertex = vector_bnd_vertices.size();
35575 for (
unsigned inod = 0; inod < n_vertex - 1; inod++)
35578 double zeta_left = vector_bnd_vertices[inod][0];
35582 for (
unsigned i = 0;
i < 2;
i++)
35584 R_left[
i] = vector_bnd_vertices[inod][
i + 1];
35588 double zeta_right = vector_bnd_vertices[inod + 1][0];
35592 for (
unsigned i = 0;
i < 2;
i++)
35594 R_right[
i] = vector_bnd_vertices[inod + 1][
i + 1];
35598 extended_vector.push_back(vector_bnd_vertices[inod]);
35602 double length = std::fabs(zeta_right - zeta_left);
35605 if (length > max_length_constraint)
35607 double n_pts = length / max_length_constraint;
35609 unsigned n_points =
static_cast<unsigned>(n_pts);
35610 double zeta_increment =
35611 (zeta_right - zeta_left) / ((
double)n_points + 1);
35615 for (
unsigned s = 1;
s < n_points + 1;
s++)
35618 zeta[0] = zeta_left + zeta_increment * double(
s);
35620 mesh_geom_obj_pt->
position(zeta, vertex);
35624 new_node[0] = zeta[0];
35625 new_node[1] = vertex[0];
35626 new_node[2] = vertex[1];
35629 extended_vector.push_back(new_node);
35635 extended_vector.push_back(vector_bnd_vertices[n_vertex - 1]);
35638 n_vertex = extended_vector.size();
35643 if (n_vertex != vector_bnd_vertices.size())
35645 max_length_applied =
true;
35649 vector_bnd_vertices.resize(n_vertex);
35650 for (
unsigned i = 0;
i < n_vertex;
i++)
35652 vector_bnd_vertices[
i].resize(3);
35653 vector_bnd_vertices[
i][0] = extended_vector[
i][0];
35654 vector_bnd_vertices[
i][1] = extended_vector[
i][1];
35655 vector_bnd_vertices[
i][2] = extended_vector[
i][2];
35660 delete mesh_geom_obj_pt;
35662 return max_length_applied;
35671 template<
class ELEMENT>
35674 Mesh* face_mesh_pt)
35681 this->
template build_face_mesh<ELEMENT, FaceElementAsGeomObject>(
35682 boundary_id, face_mesh_pt);
35685 unsigned n_element = face_mesh_pt->
nelement();
35687 for (
unsigned e = 0;
e < n_element;
e++)
35704 template<
class ELEMENT>
35706 const unsigned& boundary_id,
35707 Mesh* face_mesh_pt,
35708 std::map<FiniteElement*, bool>& is_inverted,
35709 bool& inverted_face_mesh)
35711 Mesh* tmp_unsorted_face_mesh_pt =
new Mesh();
35714 create_unsorted_face_mesh_representation(boundary_id,
35715 tmp_unsorted_face_mesh_pt);
35725 std::list<FiniteElement*> sorted_el_pt;
35727 sorted_el_pt.push_back(el_pt);
35730 unsigned nnod = el_pt->
nnode();
35733 unsigned count_done = 0;
35736 unsigned n_face_element = tmp_unsorted_face_mesh_pt->
nelement();
35739 std::map<FiniteElement*, bool> done_el;
35741 is_inverted.clear();
35744 for (
unsigned ee = 1; ee < n_face_element; ee++)
35748 for (
unsigned e = 1;
e < n_face_element;
e++)
35754 if (!done_el[el_pt])
35758 std::list<FiniteElement*>::iterator it = sorted_el_pt.end();
35763 Node* left_node_pt = first_el_pt->
node_pt(0);
35764 if (is_inverted[first_el_pt])
35766 left_node_pt = first_el_pt->
node_pt(nnod - 1);
35768 Node* right_node_pt = last_el_pt->
node_pt(nnod - 1);
35769 if (is_inverted[last_el_pt])
35771 right_node_pt = last_el_pt->
node_pt(0);
35775 if (left_node_pt == el_pt->node_pt(nnod - 1))
35777 sorted_el_pt.push_front(el_pt);
35778 done_el[el_pt] =
true;
35780 is_inverted[el_pt] =
false;
35784 else if (left_node_pt == el_pt->node_pt(0))
35786 sorted_el_pt.push_front(el_pt);
35787 done_el[el_pt] =
true;
35789 is_inverted[el_pt] =
true;
35793 else if (right_node_pt == el_pt->node_pt(0))
35795 sorted_el_pt.push_back(el_pt);
35796 done_el[el_pt] =
true;
35798 is_inverted[el_pt] =
false;
35802 else if (right_node_pt == el_pt->node_pt(nnod - 1))
35804 sorted_el_pt.push_back(el_pt);
35805 done_el[el_pt] =
true;
35807 is_inverted[el_pt] =
true;
35810 if (done_el[el_pt])
35819 if (count_done != (n_face_element - 1))
35821 std::ostringstream error_message;
35822 error_message <<
"When ordering FaceElements on "
35823 <<
"boundary " << boundary_id <<
" only managed to order \n"
35824 << count_done <<
" of " << n_face_element
35825 <<
" face elements.\n"
35828 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
35835 for (std::list<FiniteElement*>::iterator it = sorted_el_pt.begin();
35836 it != sorted_el_pt.end();
35854 this->Boundary_curve_section_pt[boundary_id];
35864 unsigned n_node = first_el_pt->
nnode();
35867 Node* first_node_pt = first_el_pt->
node_pt(0);
35868 if (is_inverted[first_el_pt])
35870 first_node_pt = first_el_pt->
node_pt(n_node - 1);
35873 double error = (first_node_pt->x(0) - first_vertex[0]) *
35874 (first_node_pt->x(0) - first_vertex[0]) +
35875 (first_node_pt->x(1) - first_vertex[1]) *
35876 (first_node_pt->x(1) - first_vertex[1]);
35878 error = sqrt(error);
35882 inverted_face_mesh =
false;
35886 inverted_face_mesh =
true;
35895 template<
class ELEMENT>
35900 unsigned n_polyline = polygon_pt->
npolyline();
35901 face_mesh_pt.resize(n_polyline);
35907 bool eligible_for_segment_redistribution =
true;
35910 for (
unsigned p = 0; p < n_polyline; p++)
35917 GeomObject*
const geom_object_pt = this->boundary_geom_object_pt(bound);
35918 if (geom_object_pt != 0)
35920 eligible_for_segment_redistribution =
false;
35923 face_mesh_pt[p] =
new Mesh();
35924 create_unsorted_face_mesh_representation(bound, face_mesh_pt[p]);
35933 if (this->nregion() > 1)
35935 std::ostringstream warn_message;
35937 <<
"Can't currently re-distribute segments between polylines if there\n"
35938 <<
"are multiple regions; returning..." << std::endl;
35940 "RefineableTriangleMesh::get_face_mesh_representation()",
35941 OOMPH_EXCEPTION_LOCATION);
35946 if (!eligible_for_segment_redistribution)
35948 std::ostringstream warn_message;
35950 <<
"Over-ruling re-distribution of segments between polylines\n"
35951 <<
"because at least one boundary is associated with a GeomObject."
35952 <<
"Returning..." << std::endl;
35954 "RefineableTriangleMesh::get_face_mesh_representation()",
35955 OOMPH_EXCEPTION_LOCATION);
35963 double s_total = 0.0;
35969 std::vector<bool> is_reversed(n_polyline,
false);
35972 for (
unsigned p = 0; p < n_polyline; p++)
35978 std::list<FiniteElement*> ordered_el_pt;
35979 FiniteElement* el_pt = face_mesh_pt[p]->finite_element_pt(0);
35980 ordered_el_pt.push_back(el_pt);
35983 unsigned nnod = el_pt->
nnode();
35986 first_polyline_node_pt[p] = el_pt->
node_pt(0);
35987 last_polyline_node_pt[p] = el_pt->
node_pt(nnod - 1);
35990 unsigned count_done = 0;
35993 unsigned n_face_element = face_mesh_pt[p]->nelement();
35999 std::map<FiniteElement*, bool> done_el;
36002 std::map<FiniteElement*, bool> is_inverted;
36005 for (
unsigned ee = 1; ee < n_face_element; ee++)
36009 for (
unsigned e = 1;
e < n_face_element;
e++)
36012 el_pt = face_mesh_pt[p]->finite_element_pt(
e);
36015 if (!done_el[el_pt])
36019 std::list<FiniteElement*>::iterator it = ordered_el_pt.end();
36024 Node* left_node_pt = first_el_pt->
node_pt(0);
36025 if (is_inverted[first_el_pt])
36027 left_node_pt = first_el_pt->
node_pt(nnod - 1);
36029 Node* right_node_pt = last_el_pt->
node_pt(nnod - 1);
36030 if (is_inverted[last_el_pt])
36032 right_node_pt = last_el_pt->
node_pt(0);
36036 if (left_node_pt == el_pt->node_pt(nnod - 1))
36038 ordered_el_pt.push_front(el_pt);
36039 done_el[el_pt] =
true;
36041 is_inverted[el_pt] =
false;
36042 first_polyline_node_pt[p] = el_pt->node_pt(0);
36046 else if (left_node_pt == el_pt->node_pt(0))
36048 ordered_el_pt.push_front(el_pt);
36049 done_el[el_pt] =
true;
36051 is_inverted[el_pt] =
true;
36052 first_polyline_node_pt[p] = el_pt->node_pt(nnod - 1);
36056 else if (right_node_pt == el_pt->node_pt(0))
36058 ordered_el_pt.push_back(el_pt);
36059 done_el[el_pt] =
true;
36061 is_inverted[el_pt] =
false;
36062 last_polyline_node_pt[p] = el_pt->node_pt(nnod - 1);
36066 else if (right_node_pt == el_pt->node_pt(nnod - 1))
36068 ordered_el_pt.push_back(el_pt);
36069 done_el[el_pt] =
true;
36071 is_inverted[el_pt] =
true;
36072 last_polyline_node_pt[p] = el_pt->node_pt(0);
36075 if (done_el[el_pt])
36084 if (count_done != (n_face_element - 1))
36086 std::ostringstream error_message;
36087 error_message <<
"When ordering FaceElements on "
36088 <<
"boundary " << bound <<
" only managed to order \n"
36089 << count_done <<
" of " << n_face_element
36090 <<
" face elements.\n"
36093 OOMPH_CURRENT_FUNCTION,
36094 OOMPH_EXCEPTION_LOCATION);
36098 ordered_face_mesh_pt[p] =
new Mesh;
36101 for (std::list<FiniteElement*>::iterator it = ordered_el_pt.begin();
36102 it != ordered_el_pt.end();
36109 ordered_face_mesh_pt[p]->add_element_pt(el_pt);
36113 for (
unsigned e = 0;
e < n_face_element; ++
e)
36115 FiniteElement* el_pt = ordered_face_mesh_pt[p]->finite_element_pt(
e);
36116 unsigned n_node = el_pt->
nnode();
36117 double element_length_squared = 0.0;
36118 for (
unsigned i = 0;
i < 2;
i++)
36120 element_length_squared +=
36125 double element_length = sqrt(element_length_squared);
36128 s_total += element_length;
36132 face_mesh_pt[p]->flush_element_and_node_storage();
36136 if ((last_polyline_node_pt[0] == first_polyline_node_pt[1]) ||
36137 (last_polyline_node_pt[0] == last_polyline_node_pt[1]))
36139 is_reversed[0] =
false;
36141 else if ((first_polyline_node_pt[0] == first_polyline_node_pt[1]) ||
36142 (first_polyline_node_pt[0] == last_polyline_node_pt[1]))
36144 is_reversed[0] =
true;
36149 std::vector<bool> mesh_done(n_polyline,
false);
36153 tmp_face_mesh_pt[0] = ordered_face_mesh_pt[0];
36154 unsigned current = 0;
36155 old_polyline_number[0] = 0;
36156 unsigned count_found = 0;
36159 for (
unsigned p = 1; p < n_polyline; p++)
36161 Node* end_node_pt = last_polyline_node_pt[current];
36162 if (is_reversed[current])
36164 end_node_pt = first_polyline_node_pt[current];
36168 for (
unsigned pp = 1; pp < n_polyline; pp++)
36170 if (!mesh_done[pp])
36173 if ((!is_reversed[current]) &&
36174 (end_node_pt == first_polyline_node_pt[pp]))
36176 tmp_face_mesh_pt[p] = ordered_face_mesh_pt[pp];
36177 mesh_done[pp] =
true;
36178 is_reversed[pp] =
false;
36179 old_polyline_number[p] = pp;
36186 else if ((!is_reversed[current]) &&
36187 (end_node_pt == last_polyline_node_pt[pp]))
36189 tmp_face_mesh_pt[p] = ordered_face_mesh_pt[pp];
36190 mesh_done[pp] =
true;
36191 is_reversed[pp] =
true;
36192 old_polyline_number[p] = pp;
36199 else if ((is_reversed[current]) &&
36200 (end_node_pt == first_polyline_node_pt[pp]))
36202 tmp_face_mesh_pt[p] = ordered_face_mesh_pt[pp];
36203 mesh_done[pp] =
true;
36204 is_reversed[pp] =
false;
36205 old_polyline_number[p] = pp;
36212 else if ((is_reversed[current]) &&
36213 (end_node_pt == last_polyline_node_pt[pp]))
36215 tmp_face_mesh_pt[p] = ordered_face_mesh_pt[pp];
36216 mesh_done[pp] =
true;
36217 is_reversed[pp] =
true;
36218 old_polyline_number[p] = pp;
36228 if (count_found != n_polyline - 1)
36230 std::ostringstream error_message;
36231 error_message <<
"Only found " << count_found <<
" out of "
36232 << n_polyline - 1 <<
" polylines to be fitted in.\n";
36234 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
36239 for (
unsigned i = 0;
i < n_polyline;
i++)
36241 ordered_face_mesh_pt[
i] = tmp_face_mesh_pt[
i];
36247 unsigned new_face_id = 0;
36251 std::map<Node*, std::map<unsigned, unsigned>>
36252 node_must_not_be_removed_from_boundary_flag;
36255 for (
unsigned p = 0; p < n_polyline; p++)
36258 unsigned n_face_element = ordered_face_mesh_pt[p]->nelement();
36259 for (
unsigned e = 0;
e < n_face_element;
e++)
36261 unsigned el_number =
e;
36262 if (is_reversed[p])
36264 el_number = n_face_element -
e - 1;
36268 ordered_face_mesh_pt[p]->finite_element_pt(el_number);
36269 unsigned n_node = el_pt->
nnode();
36272 double element_length_squared = 0.0;
36273 for (
unsigned i = 0;
i < 2;
i++)
36275 element_length_squared +=
36278 double element_length = sqrt(element_length_squared);
36281 s += element_length;
36285 if (
s < s_total /
double(n_polyline) + 1
e-6)
36288 face_mesh_pt[new_face_id]->add_element_pt(el_pt);
36290 unsigned bound_old =
36293 unsigned bound_new =
36297 for (
unsigned i = 0;
i < n_node;
i++)
36304 if (bound_new != bound_old)
36307 add_boundary_node(bound_new, nod_pt);
36311 node_must_not_be_removed_from_boundary_flag[nod_pt][bound_old] +=
36321 node_must_not_be_removed_from_boundary_flag[nod_pt][bound_old] +=
36334 if (new_face_id != n_polyline - 1)
36352 unsigned move_count = 0;
36353 for (std::map<Node*, std::map<unsigned, unsigned>>::iterator it =
36354 node_must_not_be_removed_from_boundary_flag.begin();
36355 it != node_must_not_be_removed_from_boundary_flag.end();
36359 Node* nod_pt = (*it).first;
36362 for (std::map<unsigned, unsigned>::iterator it_2 = (*it).second.begin();
36363 it_2 != (*it).second.end();
36367 unsigned bound = (*it_2).first;
36370 if ((*it_2).second == 0)
36372 remove_boundary_node(bound, nod_pt);
36379 for (
unsigned p = 0; p < n_polyline; p++)
36385 unsigned n_face_element = face_mesh_pt[p]->nelement();
36386 for (
unsigned e = 0;
e < n_face_element;
e++)
36391 face_mesh_pt[p]->element_pt(
e));
36399 setup_boundary_element_info();
36402 for (
unsigned p = 0; p < n_polyline; p++)
36408 this->
template setup_boundary_coordinates<ELEMENT>(bound);
36412 for (
unsigned p = 0; p < n_polyline; p++)
36417 ordered_face_mesh_pt[p]->flush_element_and_node_storage();
36418 delete ordered_face_mesh_pt[p];
36425 template<
class ELEMENT>
36431 face_mesh_pt.resize(n_polyline);
36434 for (
unsigned p = 0; p < n_polyline; p++)
36439 face_mesh_pt[p] =
new Mesh();
36440 create_unsorted_face_mesh_representation(bound, face_mesh_pt[p]);
36451 template<
class ELEMENT>
36454 internal_point_coord,
36455 const bool& check_only)
36459 bool update_was_performed =
false;
36461 unsigned n_hole = internal_point_coord.size();
36462 for (
unsigned ihole = 0; ihole < n_hole; ihole++)
36475 internal_point_coord[ihole].resize(2);
36489 bool update_necessary =
36490 this->update_polygon_using_face_mesh(poly_pt, check_only);
36493 if (update_necessary)
36503 update_was_performed = this->update_polygon_using_face_mesh(poly_pt);
36521 if (this->Internal_hole_point_update_fct_pt != 0)
36523 this->Internal_hole_point_update_fct_pt(ihole, poly_pt);
36530 unsigned n_polyline = poly_pt->
npolyline();
36533 vertex_coord.resize(2);
36534 internal_point_coord[ihole].resize(2);
36538 internal_point_coord[ihole][0] = 0.0;
36539 internal_point_coord[ihole][1] = 0.0;
36541 for (
unsigned p = 0; p < n_polyline; p++)
36546 for (
unsigned v = 0; v < n_vertex; v++)
36549 for (
unsigned i = 0;
i < 2;
i++)
36551 poly_ave[
i] += vertex_coord[
i];
36556 for (
unsigned i = 0;
i < 2;
i++)
36558 internal_point_coord[ihole][
i] += poly_ave[
i] / n_vertex;
36563 for (
unsigned i = 0;
i < 2;
i++)
36565 internal_point_coord[ihole][
i] /= n_polyline;
36632 return update_was_performed;
36641 template<
class ELEMENT>
36649 std::ifstream node_file(node_file_name.c_str(), std::ios_base::in);
36652 if (!node_file.is_open())
36654 std::string error_msg(
"Failed to open node file: ");
36655 error_msg +=
"\"" + node_file_name +
"\".";
36657 error_msg, OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
36662 node_file >> nnodes;
36665 unsigned dimension;
36666 node_file >> dimension;
36669 if (dimension != 2)
36672 OOMPH_CURRENT_FUNCTION,
36673 OOMPH_EXCEPTION_LOCATION);
36682 unsigned npoint_attributes;
36683 node_file >> npoint_attributes;
36687 unsigned boundary_markers_flag = 0;
36688 node_file >> boundary_markers_flag;
36691 unsigned dummy_node_number;
36693 unsigned dummy_node_attribute;
36695 unsigned dummy_node_boundary;
36699 for (
unsigned i = 0;
i < nnodes;
i++)
36701 node_file >> dummy_node_number;
36702 node_file >> x_node[
i];
36703 node_file >> y_node[
i];
36704 for (
unsigned j = 0; j < npoint_attributes; ++j)
36706 node_file >> dummy_node_attribute;
36708 if (boundary_markers_flag)
36710 node_file >> dummy_node_boundary;
36719 std::map<unsigned, Vector<std::pair<unsigned, unsigned>>>
36720 unsorted_boundary_segments;
36731 std::ifstream poly_file(poly_file_name.c_str(), std::ios_base::in);
36734 if (!poly_file.is_open())
36736 std::string error_msg(
"Failed to open poly file: ");
36737 error_msg +=
"\"" + poly_file_name +
"\".";
36739 error_msg, OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
36743 unsigned n_node_poly;
36744 poly_file >> n_node_poly;
36747 poly_file >> dimension;
36750 unsigned attribute_flag;
36751 poly_file >> attribute_flag;
36754 poly_file >> boundary_markers_flag;
36759 for (
unsigned i = 0;
i < n_node_poly;
i++)
36762 poly_file >> dummy;
36763 poly_file >> dummy;
36764 poly_file >> dummy;
36766 for (
unsigned j = 0; j < attribute_flag; ++j)
36768 poly_file >> dummy;
36771 if (boundary_markers_flag == 1)
36773 poly_file >> dummy;
36778 unsigned read_value;
36781 poly_file >> read_value;
36782 const unsigned nglobal_segments = read_value;
36785 poly_file >> boundary_markers_flag;
36788 unsigned global_segment_number;
36791 std::set<unsigned> nodes_ids;
36794 for (
unsigned i = 0;
i < nglobal_segments;
i++)
36797 unsigned lnode_id = 0;
36798 unsigned rnode_id = 0;
36799 unsigned bnd_id = 0;
36800 poly_file >> global_segment_number;
36801 poly_file >> lnode_id;
36802 poly_file >> rnode_id;
36803 nodes_ids.insert(lnode_id);
36804 nodes_ids.insert(rnode_id);
36805 if (boundary_markers_flag)
36807 poly_file >> bnd_id;
36813 unsorted_boundary_segments[bnd_id - 1].push_back(
36814 std::make_pair(lnode_id, rnode_id));
36821 const unsigned nsorted_boundaries_ids = sorted_boundaries_ids.size();
36823 bool boundary_id_found =
false;
36824 for (
unsigned ib = 0; ib < nsorted_boundaries_ids; ib++)
36826 if (sorted_boundaries_ids[ib] == bnd_id - 1)
36828 boundary_id_found =
true;
36834 if (!boundary_id_found)
36836 sorted_boundaries_ids.push_back(bnd_id - 1);
36845 if (nglobal_segments != nodes_ids.size())
36847 std::ostringstream error_message;
36849 <<
"The number of nodes (" << nodes_ids.size() <<
") and segments ("
36850 << nglobal_segments <<
") is different.\nThis may mean that there "
36851 <<
"are internal non-closed boundaries defined in\nthe polyfile. "
36852 <<
"If you need this feature please use the TriangleMeshPoyLine\n"
36853 <<
"and TriangleMeshCurviLine objects to define your domain.\n\n";
36855 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
36862 const unsigned nboundary = unsorted_boundary_segments.size();
36865 if (nboundary != this->nboundary())
36867 std::ostringstream error_message;
36869 <<
"The number of boundaries on the mesh (" << this->nboundary()
36870 <<
") is different from the number of\nboundaries read from the "
36871 <<
"polyfiles (" << unsorted_boundary_segments.size() <<
")!!!\n\n\n";
36873 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
36879 const unsigned nsorted_boundaries_ids = sorted_boundaries_ids.size();
36881 if (nsorted_boundaries_ids != this->nboundary())
36883 std::ostringstream error_message;
36885 <<
"The number of boundaries on the mesh (" << this->nboundary()
36886 <<
") is different from the number of\nsorted boundaries ids read "
36887 <<
"from the polyfiles (" << nsorted_boundaries_ids <<
")!!!\n\n\n";
36889 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
36894 std::map<unsigned, std::list<unsigned>> sorted_boundary_segments;
36897 std::map<unsigned, Vector<std::pair<unsigned, unsigned>>>::iterator it;
36899 for (it = unsorted_boundary_segments.begin();
36900 it != unsorted_boundary_segments.end();
36905 const unsigned bnd_id = (*it).first;
36909 std::map<std::pair<unsigned, unsigned>,
bool> segment_done;
36910 const unsigned nsegments = segments_edges.size();
36913 std::list<unsigned> sorted_segments;
36916 unsigned left_node_id = segments_edges[0].first;
36917 unsigned right_node_id = segments_edges[0].second;
36920 sorted_segments.push_back(left_node_id);
36921 sorted_segments.push_back(right_node_id);
36924 segment_done[segments_edges[0]] =
true;
36927 unsigned nsorted_segments = 1;
36929 while (nsorted_segments < nsegments)
36931 for (
unsigned i = 1;
i < nsegments;
i++)
36934 if (!segment_done[segments_edges[
i]])
36937 unsigned current_left_node_id = segments_edges[
i].first;
36938 unsigned current_right_node_id = segments_edges[
i].second;
36942 if (current_left_node_id == right_node_id)
36946 sorted_segments.push_back(current_right_node_id);
36948 nsorted_segments++;
36950 segment_done[segments_edges[
i]] =
true;
36952 right_node_id = current_right_node_id;
36956 else if (current_right_node_id == left_node_id)
36960 sorted_segments.push_front(current_left_node_id);
36962 nsorted_segments++;
36964 segment_done[segments_edges[
i]] =
true;
36966 left_node_id = current_left_node_id;
36970 else if (current_left_node_id == left_node_id)
36974 sorted_segments.push_front(current_right_node_id);
36976 nsorted_segments++;
36978 segment_done[segments_edges[
i]] =
true;
36980 left_node_id = current_right_node_id;
36984 else if (current_right_node_id == right_node_id)
36988 sorted_segments.push_back(current_left_node_id);
36990 nsorted_segments++;
36992 segment_done[segments_edges[
i]] =
true;
36994 right_node_id = current_left_node_id;
37002 sorted_boundary_segments[bnd_id] = sorted_segments;
37008 if (sorted_boundary_segments.size() != this->nboundary())
37010 std::ostringstream error_message;
37012 <<
"The number of boundaries on the mesh (" << this->nboundary()
37013 <<
") is different from the number\nof sorted boundaries to create the "
37014 <<
"polylines (" << sorted_boundary_segments.size() <<
")\n\n";
37016 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
37023 unsigned current_polyline = 0;
37026 for (
unsigned ib = 0; ib < nsorted_boundaries_ids; ib++)
37029 const unsigned bnd_id = sorted_boundaries_ids[ib];
37034 for (std::list<unsigned>::iterator it_list =
37035 sorted_boundary_segments[bnd_id].begin();
37036 it_list != sorted_boundary_segments[bnd_id].end();
37039 nodes_ids.push_back((*it_list));
37043 const unsigned nvertices = nodes_ids.size();
37049 for (
unsigned i = 0;
i < nvertices;
i++)
37052 vertices[
i].resize(2);
37053 vertices[
i][0] = x_node[nodes_ids[
i] - 1];
37054 vertices[
i][1] = y_node[nodes_ids[
i] - 1];
37062 polylines_pt[current_polyline] =
37066 this->Boundary_curve_section_pt[bnd_id] =
37070 current_polyline++;
37077 unsigned nsorted_polylines = 0;
37080 unsigned npolygons = 0;
37086 std::map<unsigned, bool> polyline_done;
37087 while (nsorted_polylines < nboundary)
37090 std::list<TriangleMeshCurveSection*> sorted_curve_sections_pt;
37092 unsigned init_poly = 0;
37094 bool found_root_polyline =
false;
37097 for (
unsigned i = 0;
i < nboundary;
i++)
37099 if (!polyline_done[
i])
37103 nsorted_polylines++;
37106 found_root_polyline =
true;
37109 polyline_done[
i] =
true;
37111 sorted_curve_sections_pt.push_back(polylines_pt[
i]);
37118 if (!found_root_polyline)
37120 std::ostringstream error_message;
37121 error_message <<
"Was not possible to found the root polyline to "
37122 "create polygons\n\n";
37124 OOMPH_CURRENT_FUNCTION,
37125 OOMPH_EXCEPTION_LOCATION);
37130 const unsigned bnd_id = polylines_pt[init_poly]->boundary_id();
37132 unsigned left_node_id = sorted_boundary_segments[bnd_id].front();
37133 unsigned right_node_id = sorted_boundary_segments[bnd_id].back();
37136 bool closed_polygon =
false;
37141 for (
unsigned i = init_poly;
i < nboundary;
i++)
37144 if (!polyline_done[
i])
37149 const unsigned cbnd_id = polylines_pt[
i]->boundary_id();
37151 unsigned cleft_node_id = sorted_boundary_segments[cbnd_id].front();
37152 unsigned cright_node_id = sorted_boundary_segments[cbnd_id].back();
37156 if (cleft_node_id == right_node_id)
37159 sorted_curve_sections_pt.push_back(polylines_pt[
i]);
37161 polyline_done[
i] =
true;
37163 right_node_id = cright_node_id;
37165 nsorted_polylines++;
37169 else if (cright_node_id == left_node_id)
37172 sorted_curve_sections_pt.push_front(polylines_pt[
i]);
37174 polyline_done[
i] =
true;
37176 left_node_id = cleft_node_id;
37178 nsorted_polylines++;
37182 else if (cleft_node_id == left_node_id)
37185 polylines_pt[
i]->reverse();
37187 sorted_curve_sections_pt.push_front(polylines_pt[
i]);
37189 polyline_done[
i] =
true;
37191 left_node_id = cright_node_id;
37193 nsorted_polylines++;
37197 else if (cright_node_id == right_node_id)
37200 polylines_pt[
i]->reverse();
37202 sorted_curve_sections_pt.push_back(polylines_pt[
i]);
37204 polyline_done[
i] =
true;
37206 right_node_id = cleft_node_id;
37208 nsorted_polylines++;
37217 if (left_node_id == right_node_id)
37220 closed_polygon =
true;
37223 }
while (nsorted_polylines < nboundary && !closed_polygon);
37226 if (!closed_polygon)
37228 std::ostringstream error_message;
37230 <<
"It was not possible to create a closed curve, these are the "
37231 <<
"vertices of the already sorted polylines\n\n";
37232 unsigned cpolyline = 0;
37233 for (std::list<TriangleMeshCurveSection*>::iterator it_list =
37234 sorted_curve_sections_pt.begin();
37235 it_list != sorted_curve_sections_pt.end();
37238 error_message <<
"Polyline (" << cpolyline <<
")\n";
37241 const unsigned nvertex = tmp_poly_pt->
nvertex();
37242 for (
unsigned v = 0; v < nvertex; v++)
37247 error_message <<
"\n";
37251 OOMPH_CURRENT_FUNCTION,
37252 OOMPH_EXCEPTION_LOCATION);
37259 for (std::list<TriangleMeshCurveSection*>::iterator it_list =
37260 sorted_curve_sections_pt.begin();
37261 it_list != sorted_curve_sections_pt.end();
37264 tmp_sorted_curve_sections_pt.push_back((*it_list));
37272 this->Free_polygon_pt.insert(polygon_pt);
37275 polygons_pt.push_back(polygon_pt);
37288 unsigned index_outer = 0;
37290 for (
unsigned idx_outer = 0; idx_outer < npolygons; idx_outer++)
37297 bool all_inner_inside =
true;
37300 const unsigned nouter_polylines = polygons_pt[idx_outer]->npolyline();
37301 for (
unsigned p = 0; p < nouter_polylines; p++)
37304 polygons_pt[idx_outer]->polyline_pt(p);
37305 const unsigned nvertex = tmp_poly_pt->
nvertex();
37306 for (
unsigned v = 0; v < nvertex; v++)
37309 outer_vertex_coordinates.push_back(current_vertex);
37318 const unsigned ninner_polygons = polygons_pt.size() - 1;
37323 for (
unsigned i = 0;
i <= ninner_polygons;
i++)
37325 if (
i != idx_outer)
37328 const unsigned ninner_polylines = polygons_pt[
i]->npolyline();
37329 for (
unsigned p = 0; p < ninner_polylines; p++)
37332 const unsigned nvertex = tmp_poly_pt->
nvertex();
37333 for (
unsigned v = 0; v < nvertex; v++)
37338 inner_vertex_coordinates[
i].push_back(current_vertex);
37340 else if (
i > idx_outer)
37342 inner_vertex_coordinates[
i - 1].push_back(current_vertex);
37354 for (
unsigned i = 0;
i < ninner_polygons;
i++)
37358 const unsigned nvertex_internal = inner_vertex_coordinates[
i].size();
37359 for (
unsigned v = 0; v < nvertex_internal; v++)
37363 all_inner_inside &= this->is_point_inside_polygon_helper(
37364 outer_vertex_coordinates, current_point);
37368 if (!all_inner_inside)
37378 if (!all_inner_inside)
37388 if (all_inner_inside)
37390 index_outer = idx_outer;
37400 if (index_outer != 0)
37402 std::ostringstream warning_message;
37404 <<
"The first set of nodes listed in the input polyfiles does not\n"
37405 <<
"correspond to the outer closed boundary. This may lead to\n"
37406 <<
"problems at the adaptation stage if the holes coordinates\n"
37407 <<
"are no correctly associated to the inner closed boundaries.\n"
37408 <<
"You can check the generated mesh by calling the output() method\n"
37409 <<
"from the mesh object '(problem.mesh_pt()->output(string))'\n\n";
37411 OOMPH_CURRENT_FUNCTION,
37412 OOMPH_EXCEPTION_LOCATION);
37421 this->Outer_boundary_pt.resize(1);
37422 this->Outer_boundary_pt[0] = polygons_pt[index_outer];
37424 this->Internal_polygon_pt.resize(npolygons - 1);
37425 for (
unsigned i = 0;
i < npolygons;
i++)
37427 if (
i != index_outer)
37429 if (
i < index_outer)
37432 this->Internal_polygon_pt[
i] = polygons_pt[
i];
37434 else if (
i > index_outer)
37437 this->Internal_polygon_pt[
i - 1] = polygons_pt[
i];
37450 for (
unsigned i = 0;
i < npolygons - 1;
i++)
37453 const unsigned ninner_polylines =
37454 this->Internal_polygon_pt[
i]->npolyline();
37455 for (
unsigned p = 0; p < ninner_polylines; p++)
37458 this->Internal_polygon_pt[
i]->polyline_pt(p);
37461 const unsigned nvertex = tmp_poly_pt->
nvertex();
37462 for (
unsigned v = 0; v < nvertex; v++)
37465 inner_vertex_coordinates[
i].push_back(current_vertex);
37474 poly_file >> nholes;
37477 if (npolygons > 1 && (npolygons - 1) != nholes)
37479 std::ostringstream error_message;
37481 <<
"The number of holes (" << nholes <<
") does not correspond "
37482 <<
"with the number\nof internal polygons (" << npolygons - 1 <<
")\n\n"
37483 <<
"Using polyfiles as input does not currently allows the\n"
37484 <<
"definition of more than one outer polygon\n\n";
37486 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
37494 unsigned dummy_hole;
37496 for (
unsigned ihole = 0; ihole < nholes; ihole++)
37498 hole_coordinates[ihole].resize(2);
37500 poly_file >> dummy_hole;
37501 poly_file >> hole_coordinates[ihole][0];
37502 poly_file >> hole_coordinates[ihole][1];
37508 std::map<unsigned, bool> hole_done;
37512 for (
unsigned i = 0;
i < npolygons - 1;
i++)
37515 for (
unsigned h = 0; h < nholes; h++)
37523 const bool hole_in_polygon = this->is_point_inside_polygon_helper(
37524 inner_vertex_coordinates[
i], current_point);
37527 if (hole_in_polygon)
37530 hole_done[h] =
true;
37533 index_hole_of_internal_polygon[
i] = h;
37545 if (hole_done.size() != npolygons - 1)
37547 std::ostringstream error_message;
37549 <<
"Not all the holes were associated to an internal closed boundary\n"
37550 <<
"Only (" << hole_done.size()
37551 <<
") holes were assigned for a total of\n"
37552 <<
"(" << npolygons - 1 <<
") internal closed boundaries.\n"
37553 <<
"You can check the generated mesh by calling the output() method\n"
37554 <<
"from the mesh object '(problem.mesh_pt()->output(string))'\n\n";
37556 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
37561 for (
unsigned ihole = 0; ihole < nholes; ihole++)
37564 const unsigned index_hole = index_hole_of_internal_polygon[ihole];
37569 if (index_hole != ihole)
37571 std::ostringstream error_message;
37573 <<
"The hole vertices coordinates are not listed in the same order\n"
37574 <<
"as the nodes that define the internal closed boundaries.\n"
37575 <<
"This may lead to problems in case that the holes coordinates\n"
37576 <<
"were no properly assigned to the internal closed boundaries.\n"
37577 <<
"You can check the generated mesh by calling the output() method\n"
37578 <<
"from the mesh object '(problem.mesh_pt()->output(string))'\n\n";
37580 OOMPH_CURRENT_FUNCTION,
37581 OOMPH_EXCEPTION_LOCATION);
37586 this->Internal_polygon_pt[ihole]->internal_point() =
37587 hole_coordinates[index_hole];
37591 poly_file.ignore(80,
'\n');
37601 getline(poly_file, regions_info_string);
37605 if (isdigit(regions_info_string.c_str()[0]))
37607 nregions = std::atoi(regions_info_string.c_str());
37615 std::map<unsigned, Vector<double>> regions_coordinates;
37618 unsigned dummy_region;
37620 unsigned region_id;
37623 for (
unsigned iregion = 0; iregion < nregions; iregion++)
37627 poly_file >> dummy_region;
37628 poly_file >> tmp_region_coordinates[0];
37629 poly_file >> tmp_region_coordinates[1];
37630 poly_file >> region_id;
37631 regions_coordinates[region_id].resize(2);
37632 regions_coordinates[region_id][0] = tmp_region_coordinates[0];
37633 regions_coordinates[region_id][1] = tmp_region_coordinates[1];
37636 poly_file.ignore(80,
'\n');
37639 if (region_id == 0)
37641 std::ostringstream error_message;
37643 <<
"Please use another region id different from zero.\n"
37644 <<
"It is internally used as the default region number.\n";
37646 OOMPH_CURRENT_FUNCTION,
37647 OOMPH_EXCEPTION_LOCATION);
37652 this->Regions_coordinates = regions_coordinates;
37661 template<
class ELEMENT>
37666 unsigned update_was_performed =
false;
37668 const unsigned nele = this->nelement();
37679 get_face_mesh_representation(polygon_pt, face_mesh_pt);
37687 unsigned n_polyline = polygon_pt->
npolyline();
37690 for (
unsigned p = 0; p < n_polyline; p++)
37704 std::set<Vector<double>> vertex_nodes;
37715#ifdef OOMPH_HAS_MPI
37745 const unsigned nface_element = face_mesh_pt[p]->nelement();
37752 std::map<FiniteElement*, unsigned> face_element_index_on_boundary;
37754 for (
unsigned ef = 0; ef < nface_element; ++ef)
37756 FiniteElement* ele_face_pt = face_mesh_pt[p]->finite_element_pt(ef);
37757#ifdef OOMPH_HAS_MPI
37759 if (this->is_mesh_distributed() && ele_face_pt->
is_halo())
37765 non_halo_face_element_pt.push_back(ele_face_pt);
37766 face_element_index_on_boundary[ele_face_pt] = ef;
37770 const unsigned nnon_halo_face_element = non_halo_face_element_pt.size();
37773 std::map<FiniteElement*, bool> face_element_done;
37776 unsigned nsorted_face_elements = 0;
37778#ifdef OOMPH_HAS_MPI
37780 unsigned nsub_boundaries = 0;
37785 while (nsorted_face_elements < nnon_halo_face_element)
37790 bool found_initial_face_element =
false;
37793 unsigned iface = 0;
37794 for (iface = 0; iface < nnon_halo_face_element; iface++)
37796 ele_face_pt = non_halo_face_element_pt[iface];
37798 if (!face_element_done[ele_face_pt])
37801 found_initial_face_element =
true;
37803 nsorted_face_elements++;
37810 if (!found_initial_face_element)
37812 std::ostringstream error_message;
37813 error_message <<
"Could not find an initial face element for the "
37814 "current segment\n";
37817 error_message.str(),
37818 "RefineableTriangleMesh::update_polygon_using_elements_area()",
37819 OOMPH_EXCEPTION_LOCATION);
37826 std::set<Vector<double>> local_vertex_nodes;
37834 std::set<Vector<double>> sorted_target_areas;
37844 unsigned nnode = ele_face_pt->
nnode();
37847 ele_face_pt->
node_pt(0)->get_coordinates_on_boundary(bound, bound_left);
37848 vertex_coord[0] = bound_left[0];
37851 for (
unsigned i = 0;
i < 2;
i++)
37853 vertex_coord[
i + 1] = ele_face_pt->
node_pt(0)->x(
i);
37855 local_vertex_nodes.insert(vertex_coord);
37859 ele_face_pt->
node_pt(nnode - 1)->get_coordinates_on_boundary(
37860 bound, bound_right);
37861 vertex_coord[0] = bound_right[0];
37864 for (
unsigned i = 0;
i < 2;
i++)
37866 vertex_coord[
i + 1] = ele_face_pt->
node_pt(nnode - 1)->x(
i);
37868 local_vertex_nodes.insert(vertex_coord);
37871 Node* first_node_pt = ele_face_pt->
node_pt(0);
37872 Node* last_node_pt = ele_face_pt->
node_pt(nnode - 1);
37875 face_element_done[ele_face_pt] =
true;
37887 zeta_target_area_values[0] = std::min(bound_left[0], bound_right[0]);
37890 unsigned ef = face_element_index_on_boundary[ele_face_pt];
37892 FiniteElement* el_pt = this->boundary_element_pt(bound, ef);
37895 bool found_global_element_index =
false;
37897 for (
unsigned eg = 0; eg < nele; eg++)
37900 FiniteElement* el_compare_pt = this->finite_element_pt(eg);
37904 if (el_pt == el_compare_pt)
37906 zeta_target_area_values[1] = target_area[eg];
37908 found_global_element_index =
true;
37915 if (!found_global_element_index)
37917 std::ostringstream error_message;
37918 error_message <<
"The global index for the (" << ef
37919 <<
")-th face element "
37920 <<
"on\nthe (" << bound
37921 <<
")-th boundary was not found!!!";
37923 error_message.str(),
37924 "RefineableTriangleMesh::update_polygon_using_elements_area()",
37925 OOMPH_EXCEPTION_LOCATION);
37930 sorted_target_areas.insert(zeta_target_area_values);
37935 bool face_element_added =
false;
37945 for (
unsigned iiface = iface; iiface < nnon_halo_face_element;
37948 face_element_added =
false;
37949 ele_face_pt = non_halo_face_element_pt[iiface];
37950 if (!face_element_done[ele_face_pt])
37953 nnode = ele_face_pt->nnode();
37954 Node* left_node_pt = ele_face_pt->node_pt(0);
37955 Node* right_node_pt = ele_face_pt->node_pt(nnode - 1);
37957 if (left_node_pt == first_node_pt)
37959 first_node_pt = right_node_pt;
37960 face_element_added =
true;
37962 else if (left_node_pt == last_node_pt)
37964 last_node_pt = right_node_pt;
37965 face_element_added =
true;
37967 else if (right_node_pt == first_node_pt)
37969 first_node_pt = left_node_pt;
37970 face_element_added =
true;
37972 else if (right_node_pt == last_node_pt)
37974 last_node_pt = left_node_pt;
37975 face_element_added =
true;
37978 if (face_element_added)
37982 left_node_pt->get_coordinates_on_boundary(bound, bound_left);
37983 vertex_coord[0] = bound_left[0];
37986 for (
unsigned i = 0;
i < 2;
i++)
37988 vertex_coord[
i + 1] = left_node_pt->x(
i);
37990 local_vertex_nodes.insert(vertex_coord);
37994 right_node_pt->get_coordinates_on_boundary(bound, bound_right);
37995 vertex_coord[0] = bound_right[0];
37998 for (
unsigned i = 0;
i < 2;
i++)
38000 vertex_coord[
i + 1] = right_node_pt->x(
i);
38002 local_vertex_nodes.insert(vertex_coord);
38006 face_element_done[ele_face_pt] =
true;
38007 nsorted_face_elements++;
38015 zeta_target_area_values[0] =
38016 std::min(bound_left[0], bound_right[0]);
38019 ef = face_element_index_on_boundary[ele_face_pt];
38020 FiniteElement* lel_pt = this->boundary_element_pt(bound, ef);
38023 found_global_element_index =
false;
38025 for (
unsigned eg = 0; eg < nele; eg++)
38028 FiniteElement* lel_compare_pt = this->finite_element_pt(eg);
38032 if (lel_pt == lel_compare_pt)
38034 zeta_target_area_values[1] = target_area[eg];
38036 found_global_element_index =
true;
38043 if (!found_global_element_index)
38045 std::ostringstream error_message;
38046 error_message <<
"The global index for the (" << ef
38047 <<
")-th face element "
38048 <<
"on\nthe (" << bound
38049 <<
")-th boundary was not found!!!";
38051 "RefineableTriangleMesh::update_polygon_"
38052 "using_elements_area()",
38053 OOMPH_EXCEPTION_LOCATION);
38058 sorted_target_areas.insert(zeta_target_area_values);
38065 }
while (face_element_added &&
38066 (nsorted_face_elements < nnon_halo_face_element));
38074 const unsigned nlocal_nodes = local_vertex_nodes.size();
38076 local_tmp_vector_vertex_node.resize(nlocal_nodes);
38079 unsigned counter = 0;
38080 std::set<Vector<double>>::iterator it_vertex;
38081 for (it_vertex = local_vertex_nodes.begin();
38082 it_vertex != local_vertex_nodes.end();
38085 local_tmp_vector_vertex_node[counter].resize(3);
38086 local_tmp_vector_vertex_node[counter][0] = (*it_vertex)[0];
38087 local_tmp_vector_vertex_node[counter][1] = (*it_vertex)[1];
38088 local_tmp_vector_vertex_node[counter][2] = (*it_vertex)[2];
38094 const unsigned ntarget_areas = sorted_target_areas.size();
38095 tmp_sorted_target_areas.resize(ntarget_areas);
38097 std::set<Vector<double>>::iterator it_area;
38098 for (it_area = sorted_target_areas.begin();
38099 it_area != sorted_target_areas.end();
38102 tmp_sorted_target_areas[counter] = (*it_area)[1];
38107 if (nlocal_nodes > 0 && (ntarget_areas != nlocal_nodes - 1))
38109 std::ostringstream error_message;
38111 <<
"The boundary (" << bound <<
") was split during the "
38112 <<
"distribution process.\n"
38113 <<
"The problem is in the association of the target areas with "
38115 <<
"elements that gave rise to the vertex coordinates.\n"
38116 <<
"The number of local nodes (" << nlocal_nodes
38117 <<
"), on the 'sub-polyline', is not\n"
38118 <<
"according with the number of target "
38119 <<
"areas (" << ntarget_areas <<
")\nfor that number of nodes.\n"
38120 <<
"The target areas number MUST be equal to the number of\n"
38121 <<
"local nodes minus one\n\n";
38123 OOMPH_CURRENT_FUNCTION,
38124 OOMPH_EXCEPTION_LOCATION);
38135 double unrefinement_tolerance =
38139 bool unrefinement_applied =
38140 unrefine_boundary_constrained_by_target_area(
38143 local_tmp_vector_vertex_node,
38144 unrefinement_tolerance,
38145 tmp_sorted_target_areas);
38148 double refinement_tolerance =
38152 bool refinement_applied = refine_boundary_constrained_by_target_area(
38154 local_tmp_vector_vertex_node,
38155 refinement_tolerance,
38156 tmp_sorted_target_areas);
38160 local_vertex_nodes.clear();
38165 unsigned nnew_nodes = local_tmp_vector_vertex_node.size();
38166 for (
unsigned i = 0;
i < nnew_nodes;
i++)
38168 vertex_coord[0] = local_tmp_vector_vertex_node[
i][0];
38169 vertex_coord[1] = local_tmp_vector_vertex_node[
i][1];
38170 vertex_coord[2] = local_tmp_vector_vertex_node[
i][2];
38171 vertex_nodes.insert(vertex_coord);
38172 local_vertex_nodes.insert(vertex_coord);
38177 update_was_performed = (unrefinement_applied || refinement_applied);
38179#ifdef OOMPH_HAS_MPI
38180 if (this->is_mesh_distributed())
38184 sub_vertex_nodes.push_back(local_vertex_nodes);
38193 unsigned npoly_vertex = vertex_nodes.size();
38196 tmp_vector_vertex_node.resize(npoly_vertex);
38197 unsigned count = 0;
38198 for (std::set<
Vector<double>>::iterator it = vertex_nodes.begin();
38199 it != vertex_nodes.end();
38202 tmp_vector_vertex_node[count].resize(3);
38203 tmp_vector_vertex_node[count][0] = (*it)[0];
38204 tmp_vector_vertex_node[count][1] = (*it)[1];
38205 tmp_vector_vertex_node[count][2] = (*it)[2];
38209#ifdef OOMPH_HAS_MPI
38212 unsigned nsub_boundaries_set = sub_vertex_nodes.size();
38213 if (nsub_boundaries_set != nsub_boundaries)
38215 std::ostringstream error_message;
38217 <<
"The number of found sub-boundaries and the number of counted\n"
38218 <<
"sub-boundaries are different:\n"
38219 <<
"Number of found sub-boundaries: (" << nsub_boundaries_set <<
")\n"
38220 <<
"Number of counted sub-boundaries: (" << nsub_boundaries <<
")\n";
38222 OOMPH_CURRENT_FUNCTION,
38223 OOMPH_EXCEPTION_LOCATION);
38228 if (this->is_mesh_distributed() && nsub_boundaries > 1)
38231 this->Boundary_was_splitted[bound] =
true;
38233 sub_tmp_vector_vertex_node.resize(nsub_boundaries);
38234 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
38237 const unsigned nsubpoly_vertex = sub_vertex_nodes[isub].size();
38238 sub_tmp_vector_vertex_node[isub].resize(nsubpoly_vertex);
38239 unsigned subcount = 0;
38240 std::set<Vector<double>>::iterator subit;
38241 for (subit = sub_vertex_nodes[isub].begin();
38242 subit != sub_vertex_nodes[isub].end();
38245 sub_tmp_vector_vertex_node[isub][subcount].resize(3);
38246 sub_tmp_vector_vertex_node[isub][subcount][0] = (*subit)[0];
38247 sub_tmp_vector_vertex_node[isub][subcount][1] = (*subit)[1];
38248 sub_tmp_vector_vertex_node[isub][subcount][2] = (*subit)[2];
38258 unsigned n_vertex = tmp_vector_vertex_node.size();
38261 vector_vertex_node.resize(n_vertex);
38262 for (
unsigned i = 0;
i < n_vertex;
i++)
38264 vector_vertex_node[
i].resize(2);
38265 vector_vertex_node[
i][0] = tmp_vector_vertex_node[
i][1];
38266 vector_vertex_node[
i][1] = tmp_vector_vertex_node[
i][2];
38269#ifdef OOMPH_HAS_MPI
38272 if (this->is_mesh_distributed() && nsub_boundaries > 1)
38277 sub_vector_vertex_node.resize(nsub_boundaries);
38278 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
38280 const unsigned subn_vertex = sub_tmp_vector_vertex_node[isub].size();
38282 sub_vector_vertex_node[isub].resize(subn_vertex);
38283 for (
unsigned i = 0;
i < subn_vertex;
i++)
38285 sub_vector_vertex_node[isub][
i].resize(2);
38286 sub_vector_vertex_node[isub][
i][0] =
38287 sub_tmp_vector_vertex_node[isub][
i][1];
38288 sub_vector_vertex_node[isub][
i][1] =
38289 sub_tmp_vector_vertex_node[isub][
i][2];
38304#ifdef OOMPH_HAS_MPI
38308 if (!this->is_mesh_distributed())
38315 unsigned n_prev_vertex =
38317 final_vertex_of_previous_segment =
38321 unsigned prev_seg_boundary_id =
38326 double error = 0.0;
38327 for (
unsigned i = 0;
i < 2;
i++)
38329 const double dist = final_vertex_of_previous_segment[
i] -
38330 (*vector_vertex_node.begin())[
i];
38331 error += dist * dist;
38333 error = sqrt(error);
38341 double rev_error = 0.0;
38342 for (
unsigned i = 0;
i < 2;
i++)
38344 const double dist = final_vertex_of_previous_segment[
i] -
38345 (*--vector_vertex_node.end())[
i];
38346 rev_error += dist * dist;
38348 rev_error = sqrt(rev_error);
38362 initial_vertex_of_previous_segment =
38365 unsigned prev_seg_boundary_id =
38370 double error = 0.0;
38371 for (
unsigned i = 0;
i < 2;
i++)
38373 const double dist = initial_vertex_of_previous_segment[
i] -
38374 (*vector_vertex_node.begin())[
i];
38375 error += dist * dist;
38377 error = sqrt(error);
38386 double rev_error = 0.0;
38387 for (
unsigned i = 0;
i < 2;
i++)
38389 const double dist = initial_vertex_of_previous_segment[
i] -
38390 (*--vector_vertex_node.end())[
i];
38391 rev_error += dist * dist;
38400 std::ostringstream error_stream;
38402 <<
"The distance between the first node of the current\n"
38403 <<
"line segment (boundary " << bound
38404 <<
") and either end of "
38405 <<
"the previous line segment\n"
38406 <<
"(boundary " << prev_seg_boundary_id
38407 <<
") is bigger than "
38408 <<
"the desired tolerance "
38411 <<
"This suggests that the polylines defining the "
38413 <<
"representation are not properly ordered.\n"
38414 <<
"Fail on last vertex of polyline: ("
38415 << prev_seg_boundary_id <<
") and\n"
38416 <<
"first vertex of polyline (" << bound <<
").\n"
38417 <<
"This should have failed when first trying to "
38418 <<
"construct the\npolygon.\n";
38420 OOMPH_CURRENT_FUNCTION,
38421 OOMPH_EXCEPTION_LOCATION);
38428 std::reverse(vector_vertex_node.begin(),
38429 vector_vertex_node.end());
38443 std::ostringstream error_stream;
38445 <<
"The distance between the first node of the current\n"
38446 <<
"line segment (boundary " << bound
38447 <<
") and either end of "
38448 <<
"the previous line segment\n"
38449 <<
"(boundary " << prev_seg_boundary_id
38450 <<
") is bigger than the "
38451 <<
"desired tolerance "
38454 <<
"This suggests that the polylines defining the polygonal\n"
38455 <<
"representation are not properly ordered.\n"
38456 <<
"Fail on last vertex of polyline: ("
38457 << prev_seg_boundary_id <<
") and\nfirst vertex of polyline ("
38459 <<
"This should have failed when first trying to construct"
38460 <<
" the polygon.\n";
38462 OOMPH_CURRENT_FUNCTION,
38463 OOMPH_EXCEPTION_LOCATION);
38469 std::reverse(vector_vertex_node.begin(),
38470 vector_vertex_node.end());
38488 n_vertex = vector_vertex_node.size();
38500 double unrefinement_tolerance =
38504 double refinement_tolerance =
38515#ifdef OOMPH_HAS_MPI
38518 if (this->is_mesh_distributed())
38524 this->copy_connection_information(polygon_pt->
polyline_pt(p),
38525 tmp_curve_section_pt);
38533 this->copy_connection_information(polygon_pt->
polyline_pt(p),
38534 tmp_curve_section_pt);
38540 bool delete_it_on_destructor =
false;
38542 std::set<TriangleMeshCurveSection*>::iterator it =
38545 if (it != this->Free_curve_section_pt.end())
38547 this->Free_curve_section_pt.erase(it);
38549 delete_it_on_destructor =
true;
38559 if (delete_it_on_destructor)
38564#ifdef OOMPH_HAS_MPI
38567 if (this->is_mesh_distributed() && nsub_boundaries > 1)
38573 this->Boundary_subpolylines[bound].clear();
38576 this->Boundary_subpolylines[bound].resize(nsub_boundaries);
38577 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
38585 this->Boundary_subpolylines[bound][isub] = sub_tmp_polyline_pt;
38601 delete mesh_geom_obj_pt;
38606 for (
unsigned p = 0; p < n_polyline; p++)
38608 face_mesh_pt[p]->flush_node_storage();
38609 delete face_mesh_pt[p];
38612 return update_was_performed;
38619 template<
class ELEMENT>
38624 unsigned update_was_performed =
false;
38626 const unsigned nele = this->nelement();
38637 get_face_mesh_representation(open_curve_pt, face_mesh_pt);
38645 const unsigned ncurve_section = open_curve_pt->
ncurve_section();
38648 for (
unsigned cs = 0; cs < ncurve_section; cs++)
38663 const unsigned chunk =
38673 const unsigned nface_element = face_mesh_pt[cs]->nelement();
38681 std::map<FiniteElement*, unsigned> face_element_index_on_boundary;
38684 std::map<FiniteElement*, bool> face_element_done;
38686 for (
unsigned ef = 0; ef < nface_element; ++ef)
38688 FiniteElement* ele_face_pt = face_mesh_pt[cs]->finite_element_pt(ef);
38693#ifdef OOMPH_HAS_MPI
38694 if (this->is_mesh_distributed())
38705 if (!face_element_done[ele_face_pt])
38710 non_halo_doubled_face_element_pt.push_back(ele_face_pt);
38712 face_element_index_on_boundary[ele_face_pt] = ef;
38714 face_element_done[ele_face_pt] =
true;
38716 const unsigned nnodes = ele_face_pt->
nnode();
38719 Node* left_node_pt = ele_face_pt->
node_pt(0);
38720 Node* right_node_pt = ele_face_pt->
node_pt(nnodes - 1);
38724 bool found_other_side_face_ele =
false;
38726 for (
unsigned iface = 0; iface < nface_element; iface++)
38730 face_mesh_pt[cs]->finite_element_pt(iface);
38732 if (!face_element_done[cele_face_pt])
38734 Node* cleft_node_pt = cele_face_pt->
node_pt(0);
38735 Node* cright_node_pt = cele_face_pt->
node_pt(nnodes - 1);
38737 if ((left_node_pt == cleft_node_pt &&
38738 right_node_pt == cright_node_pt) ||
38739 (left_node_pt == cright_node_pt &&
38740 right_node_pt == cleft_node_pt))
38743 non_halo_doubled_face_element_pt.push_back(cele_face_pt);
38745 face_element_done[cele_face_pt] =
true;
38747 face_element_index_on_boundary[cele_face_pt] = iface;
38750 found_other_side_face_ele =
true;
38758 if (!found_other_side_face_ele)
38760 std::ostringstream error_message;
38762 <<
"The face element at the other side of the boundary (" << bound
38763 <<
") was not found!!\n"
38764 <<
"These are the nodes of the face element:\n"
38765 <<
"(" << left_node_pt->x(0) <<
", " << left_node_pt->x(1) <<
") "
38766 <<
"and (" << right_node_pt->x(0) <<
"," << right_node_pt->x(1)
38769 error_message.str(),
38770 "RefineableTriangleMesh::update_open_curve_using_elements_area()",
38771 OOMPH_EXCEPTION_LOCATION);
38780 face_element_done.clear();
38785 std::set<Vector<double>> vertex_nodes;
38796#ifdef OOMPH_HAS_MPI
38801 std::vector<bool> internal_to_shared_boundary;
38828 unsigned nsorted_face_elements = 0;
38830#ifdef OOMPH_HAS_MPI
38832 unsigned nsub_boundaries = 0;
38836 const unsigned nnon_halo_doubled_face_ele =
38837 non_halo_doubled_face_element_pt.size();
38841 while (nsorted_face_elements < nnon_halo_doubled_face_ele)
38847 bool found_initial_face_element =
false;
38853 bool both_root_face_elements_are_nonhalo =
false;
38855 unsigned iface = 0;
38856 for (iface = 0; iface < nnon_halo_doubled_face_ele; iface += 2)
38858 ele_face_pt = non_halo_doubled_face_element_pt[iface];
38860 if (!face_element_done[ele_face_pt])
38863 face_element_done[ele_face_pt] =
true;
38865 repeated_ele_face_pt = non_halo_doubled_face_element_pt[iface + 1];
38867 face_element_done[repeated_ele_face_pt] =
true;
38869#ifdef OOMPH_HAS_MPI
38870 if (!repeated_ele_face_pt->
is_halo())
38872 both_root_face_elements_are_nonhalo =
true;
38878 nsorted_face_elements += 2;
38882 found_initial_face_element =
true;
38889 if (!found_initial_face_element)
38891 std::ostringstream error_message;
38892 error_message <<
"Could not find an initial face element for the "
38893 "current segment\n";
38895 OOMPH_CURRENT_FUNCTION,
38896 OOMPH_EXCEPTION_LOCATION);
38903 std::set<Vector<double>> local_vertex_nodes;
38911 std::set<Vector<double>> sorted_target_areas;
38921 const unsigned nnode = ele_face_pt->
nnode();
38924 ele_face_pt->
node_pt(0)->get_coordinates_on_boundary(bound, bound_left);
38925 vertex_coord[0] = bound_left[0];
38928 for (
unsigned i = 0;
i < 2;
i++)
38930 vertex_coord[
i + 1] = ele_face_pt->
node_pt(0)->x(
i);
38932 local_vertex_nodes.insert(vertex_coord);
38936 ele_face_pt->
node_pt(nnode - 1)->get_coordinates_on_boundary(
38937 bound, bound_right);
38938 vertex_coord[0] = bound_right[0];
38941 for (
unsigned i = 0;
i < 2;
i++)
38943 vertex_coord[
i + 1] = ele_face_pt->
node_pt(nnode - 1)->x(
i);
38945 local_vertex_nodes.insert(vertex_coord);
38948 Node* first_node_pt = ele_face_pt->
node_pt(0);
38949 Node* last_node_pt = ele_face_pt->
node_pt(nnode - 1);
38961 zeta_target_area_values[0] = std::min(bound_left[0], bound_right[0]);
38964 const unsigned ef = face_element_index_on_boundary[ele_face_pt];
38966 FiniteElement* el_pt = this->boundary_element_pt(bound, ef);
38967 double target_area_face_element = 0.0;
38970 bool found_global_element_index =
false;
38972 for (
unsigned eg = 0; eg < nele; eg++)
38975 FiniteElement* el_compare_pt = this->finite_element_pt(eg);
38979 if (el_pt == el_compare_pt)
38981 target_area_face_element = target_area[eg];
38983 found_global_element_index =
true;
38990 if (!found_global_element_index)
38992 std::ostringstream error_message;
38993 error_message <<
"The global index for the (" << ef
38994 <<
")-th face element "
38995 <<
"on\nthe (" << bound
38996 <<
")-th boundary was not found!!!";
38998 OOMPH_CURRENT_FUNCTION,
38999 OOMPH_EXCEPTION_LOCATION);
39004 const unsigned ref =
39005 face_element_index_on_boundary[repeated_ele_face_pt];
39006 FiniteElement* rel_pt = this->boundary_element_pt(bound, ref);
39007 double target_area_repeated_face_element = 0.0;
39010 bool found_global_repeated_element_index =
false;
39012 for (
unsigned eg = 0; eg < nele; eg++)
39015 FiniteElement* el_compare_pt = this->finite_element_pt(eg);
39019 if (rel_pt == el_compare_pt)
39021 target_area_repeated_face_element = target_area[eg];
39023 found_global_repeated_element_index =
true;
39030 if (!found_global_repeated_element_index)
39032 std::ostringstream error_message;
39033 error_message <<
"The global index for the (" << ref
39034 <<
")-th face element "
39035 <<
"on\nthe (" << bound
39036 <<
")-th boundary was not found (repeated "
39037 <<
"face element)!!!";
39039 OOMPH_CURRENT_FUNCTION,
39040 OOMPH_EXCEPTION_LOCATION);
39046 zeta_target_area_values[1] =
39047 std::min(target_area_face_element, target_area_repeated_face_element);
39050 sorted_target_areas.insert(zeta_target_area_values);
39055 bool face_element_added =
false;
39065 for (
unsigned iiface = iface; iiface < nnon_halo_doubled_face_ele;
39068 face_element_added =
false;
39069 ele_face_pt = non_halo_doubled_face_element_pt[iiface];
39076 repeated_ele_face_pt = non_halo_doubled_face_element_pt[iiface + 1];
39077 bool both_face_elements_are_nonhalo =
false;
39079#ifdef OOMPH_HAS_MPI
39080 if (!repeated_ele_face_pt->
is_halo())
39082 both_face_elements_are_nonhalo =
true;
39086 if (!face_element_done[ele_face_pt] &&
39087 (both_face_elements_are_nonhalo ==
39088 both_root_face_elements_are_nonhalo))
39091 const unsigned nlnode = ele_face_pt->
nnode();
39092 Node* left_node_pt = ele_face_pt->
node_pt(0);
39093 Node* right_node_pt = ele_face_pt->
node_pt(nlnode - 1);
39095 if (left_node_pt == first_node_pt)
39097 first_node_pt = right_node_pt;
39098 face_element_added =
true;
39100 else if (left_node_pt == last_node_pt)
39102 last_node_pt = right_node_pt;
39103 face_element_added =
true;
39105 else if (right_node_pt == first_node_pt)
39107 first_node_pt = left_node_pt;
39108 face_element_added =
true;
39110 else if (right_node_pt == last_node_pt)
39112 last_node_pt = left_node_pt;
39113 face_element_added =
true;
39116 if (face_element_added)
39120 left_node_pt->get_coordinates_on_boundary(bound, bound_left);
39121 vertex_coord[0] = bound_left[0];
39124 for (
unsigned i = 0;
i < 2;
i++)
39126 vertex_coord[
i + 1] = left_node_pt->x(
i);
39128 local_vertex_nodes.insert(vertex_coord);
39132 right_node_pt->get_coordinates_on_boundary(bound, bound_right);
39133 vertex_coord[0] = bound_right[0];
39136 for (
unsigned i = 0;
i < 2;
i++)
39138 vertex_coord[
i + 1] = right_node_pt->x(
i);
39140 local_vertex_nodes.insert(vertex_coord);
39144 face_element_done[ele_face_pt] =
true;
39147 repeated_ele_face_pt =
39148 non_halo_doubled_face_element_pt[iiface + 1];
39149 face_element_done[repeated_ele_face_pt] =
true;
39151 nsorted_face_elements += 2;
39159 zeta_target_area_values[0] =
39160 std::min(bound_left[0], bound_right[0]);
39163 const unsigned lef =
39164 face_element_index_on_boundary[ele_face_pt];
39165 FiniteElement* lel_pt = this->boundary_element_pt(bound, lef);
39168 found_global_element_index =
false;
39170 for (
unsigned eg = 0; eg < nele; eg++)
39173 FiniteElement* lel_compare_pt = this->finite_element_pt(eg);
39177 if (lel_pt == lel_compare_pt)
39179 target_area_face_element = target_area[eg];
39181 found_global_element_index =
true;
39188 if (!found_global_element_index)
39190 std::ostringstream error_message;
39191 error_message <<
"The global index for the (" << lef
39192 <<
")-th face element "
39193 <<
"on\nthe (" << bound
39194 <<
")-th boundary was not found!!!";
39196 OOMPH_CURRENT_FUNCTION,
39197 OOMPH_EXCEPTION_LOCATION);
39202 const unsigned rlef =
39203 face_element_index_on_boundary[repeated_ele_face_pt];
39204 FiniteElement* rlel_pt = this->boundary_element_pt(bound, rlef);
39207 found_global_repeated_element_index =
false;
39209 for (
unsigned eg = 0; eg < nele; eg++)
39212 FiniteElement* lel_compare_pt = this->finite_element_pt(eg);
39216 if (rlel_pt == lel_compare_pt)
39218 target_area_repeated_face_element = target_area[eg];
39220 found_global_repeated_element_index =
true;
39227 if (!found_global_repeated_element_index)
39229 std::ostringstream error_message;
39230 error_message <<
"The global index for the (" << rlef
39231 <<
")-th face element "
39232 <<
"on\nthe (" << bound
39233 <<
")-th boundary was not found "
39234 <<
"(repeated face element)!!!";
39236 OOMPH_CURRENT_FUNCTION,
39237 OOMPH_EXCEPTION_LOCATION);
39243 zeta_target_area_values[1] = std::min(
39244 target_area_face_element, target_area_repeated_face_element);
39247 sorted_target_areas.insert(zeta_target_area_values);
39254 }
while (face_element_added &&
39255 (nsorted_face_elements < nnon_halo_doubled_face_ele));
39263 const unsigned nlocal_nodes = local_vertex_nodes.size();
39265 local_tmp_vector_vertex_node.resize(nlocal_nodes);
39268 unsigned counter = 0;
39269 std::set<Vector<double>>::iterator it_vertex;
39270 for (it_vertex = local_vertex_nodes.begin();
39271 it_vertex != local_vertex_nodes.end();
39274 local_tmp_vector_vertex_node[counter].resize(3);
39275 local_tmp_vector_vertex_node[counter][0] = (*it_vertex)[0];
39276 local_tmp_vector_vertex_node[counter][1] = (*it_vertex)[1];
39277 local_tmp_vector_vertex_node[counter][2] = (*it_vertex)[2];
39283 const unsigned ntarget_areas = sorted_target_areas.size();
39284 tmp_sorted_target_areas.resize(ntarget_areas);
39286 std::set<Vector<double>>::iterator it_area;
39287 for (it_area = sorted_target_areas.begin();
39288 it_area != sorted_target_areas.end();
39291 tmp_sorted_target_areas[counter] = (*it_area)[1];
39296 if (nlocal_nodes > 0 && (ntarget_areas != nlocal_nodes - 1))
39298 std::ostringstream error_message;
39300 <<
"The boundary (" << bound <<
") was split during the "
39301 <<
"distribution process.\n"
39302 <<
"The problem comes when associating the target areas with the "
39303 <<
"elements that gave\nrise to the vertex coordinates.\n"
39304 <<
"The number of local nodes on the 'sub-polyline' ("
39305 << nlocal_nodes <<
") is not according with the number of target\n"
39306 <<
"areas (" << ntarget_areas <<
") for that number of nodes.\n"
39307 <<
"The target areas number must be equal to the number of "
39310 OOMPH_CURRENT_FUNCTION,
39311 OOMPH_EXCEPTION_LOCATION);
39318 if (local_tmp_vector_vertex_node[nlocal_nodes - 1][2] <
39319 local_tmp_vector_vertex_node[0][2])
39321 std::reverse(local_tmp_vector_vertex_node.begin(),
39322 local_tmp_vector_vertex_node.end());
39323 std::reverse(tmp_sorted_target_areas.begin(),
39324 tmp_sorted_target_areas.end());
39326 else if (local_tmp_vector_vertex_node[nlocal_nodes - 1][2] ==
39327 local_tmp_vector_vertex_node[0][2])
39329 if (local_tmp_vector_vertex_node[nlocal_nodes - 1][1] <
39330 local_tmp_vector_vertex_node[0][1])
39332 std::reverse(local_tmp_vector_vertex_node.begin(),
39333 local_tmp_vector_vertex_node.end());
39334 std::reverse(tmp_sorted_target_areas.begin(),
39335 tmp_sorted_target_areas.end());
39346 double unrefinement_tolerance =
39350 bool unrefinement_applied =
39351 unrefine_boundary_constrained_by_target_area(
39354 local_tmp_vector_vertex_node,
39355 unrefinement_tolerance,
39356 tmp_sorted_target_areas);
39359 double refinement_tolerance =
39363 bool refinement_applied = refine_boundary_constrained_by_target_area(
39365 local_tmp_vector_vertex_node,
39366 refinement_tolerance,
39367 tmp_sorted_target_areas);
39371 local_vertex_nodes.clear();
39376 const unsigned nnew_nodes = local_tmp_vector_vertex_node.size();
39377 for (
unsigned i = 0;
i < nnew_nodes;
i++)
39379 vertex_coord[0] = local_tmp_vector_vertex_node[
i][0];
39380 vertex_coord[1] = local_tmp_vector_vertex_node[
i][1];
39381 vertex_coord[2] = local_tmp_vector_vertex_node[
i][2];
39382 vertex_nodes.insert(vertex_coord);
39383 local_vertex_nodes.insert(vertex_coord);
39388 update_was_performed = (unrefinement_applied || refinement_applied);
39390#ifdef OOMPH_HAS_MPI
39391 if (this->is_mesh_distributed())
39396 sub_vertex_nodes.push_back(local_vertex_nodes);
39402 if (both_root_face_elements_are_nonhalo)
39404 internal_to_shared_boundary.push_back(
false);
39408 internal_to_shared_boundary.push_back(
true);
39419 const unsigned npoly_vertex = vertex_nodes.size();
39420 tmp_vector_vertex_node.resize(npoly_vertex);
39421 unsigned count = 0;
39422 for (std::set<
Vector<double>>::iterator it = vertex_nodes.begin();
39423 it != vertex_nodes.end();
39426 tmp_vector_vertex_node[count].resize(3);
39427 tmp_vector_vertex_node[count][0] = (*it)[0];
39428 tmp_vector_vertex_node[count][1] = (*it)[1];
39429 tmp_vector_vertex_node[count][2] = (*it)[2];
39433#ifdef OOMPH_HAS_MPI
39438 const unsigned nsub_boundaries_set = sub_vertex_nodes.size();
39439 const unsigned ninternal_to_shared_boundaries =
39440 internal_to_shared_boundary.size();
39441 if (nsub_boundaries_set != ninternal_to_shared_boundaries)
39443 std::ostringstream error_message;
39445 <<
"The number of found sub-boundaries and the number of marked "
39446 <<
"internal\nboundaries are different\n"
39447 <<
"Number of found sub-boundaries: (" << nsub_boundaries_set <<
")\n"
39448 <<
"Number of marked internal boundaries: ("
39449 << ninternal_to_shared_boundaries <<
")\n\n";
39451 OOMPH_CURRENT_FUNCTION,
39452 OOMPH_EXCEPTION_LOCATION);
39458 if (nsub_boundaries_set != nsub_boundaries)
39460 std::ostringstream error_message;
39462 <<
"The number of found sub-boundaries and the number of counted\n"
39463 <<
"sub-boundaries are different:\n"
39464 <<
"Number of found sub-boundaries: (" << nsub_boundaries_set <<
")\n"
39465 <<
"Number of counted sub-boundaries: (" << nsub_boundaries
39468 OOMPH_CURRENT_FUNCTION,
39469 OOMPH_EXCEPTION_LOCATION);
39474 if (this->is_mesh_distributed() && nsub_boundaries > 1)
39477 this->Boundary_was_splitted[bound] =
true;
39480 sub_tmp_vector_vertex_node.resize(nsub_boundaries);
39482 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
39485 const unsigned nsubpoly_vertex = sub_vertex_nodes[isub].size();
39486 sub_tmp_vector_vertex_node[isub].resize(nsubpoly_vertex);
39487 unsigned subcount = 0;
39488 std::set<Vector<double>>::iterator subit;
39489 for (subit = sub_vertex_nodes[isub].begin();
39490 subit != sub_vertex_nodes[isub].end();
39493 sub_tmp_vector_vertex_node[isub][subcount].resize(3);
39494 sub_tmp_vector_vertex_node[isub][subcount][0] = (*subit)[0];
39495 sub_tmp_vector_vertex_node[isub][subcount][1] = (*subit)[1];
39496 sub_tmp_vector_vertex_node[isub][subcount][2] = (*subit)[2];
39506 unsigned n_vertex = tmp_vector_vertex_node.size();
39509 vector_vertex_node.resize(n_vertex);
39510 for (
unsigned i = 0;
i < n_vertex;
i++)
39512 vector_vertex_node[
i].resize(2);
39513 vector_vertex_node[
i][0] = tmp_vector_vertex_node[
i][1];
39514 vector_vertex_node[
i][1] = tmp_vector_vertex_node[
i][2];
39517#ifdef OOMPH_HAS_MPI
39520 if (this->is_mesh_distributed() && nsub_boundaries > 1)
39525 sub_vector_vertex_node.resize(nsub_boundaries);
39526 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
39528 const unsigned subn_vertex = sub_tmp_vector_vertex_node[isub].size();
39530 sub_vector_vertex_node[isub].resize(subn_vertex);
39531 for (
unsigned i = 0;
i < subn_vertex;
i++)
39533 sub_vector_vertex_node[isub][
i].resize(2);
39534 sub_vector_vertex_node[isub][
i][0] =
39535 sub_tmp_vector_vertex_node[isub][
i][1];
39536 sub_vector_vertex_node[isub][
i][1] =
39537 sub_tmp_vector_vertex_node[isub][
i][2];
39552#ifdef OOMPH_HAS_MPI
39556 if (!this->is_mesh_distributed())
39563 unsigned n_prev_vertex =
39565 final_vertex_of_previous_segment =
39567 n_prev_vertex - 1);
39569 unsigned prev_seg_boundary_id =
39574 double error = 0.0;
39575 for (
unsigned i = 0;
i < 2;
i++)
39577 const double dist = final_vertex_of_previous_segment[
i] -
39578 (*vector_vertex_node.begin())[
i];
39579 error += dist * dist;
39581 error = sqrt(error);
39589 double rev_error = 0.0;
39590 for (
unsigned i = 0;
i < 2;
i++)
39592 const double dist = final_vertex_of_previous_segment[
i] -
39593 (*--vector_vertex_node.end())[
i];
39594 rev_error += dist * dist;
39596 rev_error = sqrt(rev_error);
39610 initial_vertex_of_previous_segment =
39613 unsigned prev_seg_boundary_id =
39618 double error = 0.0;
39619 for (
unsigned i = 0;
i < 2;
i++)
39621 const double dist = initial_vertex_of_previous_segment[
i] -
39622 (*vector_vertex_node.begin())[
i];
39623 error += dist * dist;
39625 error = sqrt(error);
39634 double rev_error = 0.0;
39635 for (
unsigned i = 0;
i < 2;
i++)
39637 const double dist = initial_vertex_of_previous_segment[
i] -
39638 (*--vector_vertex_node.end())[
i];
39639 rev_error += dist * dist;
39641 rev_error = sqrt(rev_error);
39647 std::ostringstream error_stream;
39649 <<
"The distance between the first node of the current\n"
39650 <<
"line segment (boundary " << bound
39651 <<
") and either end of "
39652 <<
"the previous line segment\n"
39653 <<
"(boundary " << prev_seg_boundary_id
39654 <<
") is bigger than"
39655 <<
" the desired tolerance "
39658 <<
"This suggests that the polylines defining the "
39660 <<
"representation are not properly ordered.\n"
39661 <<
"Fail on last vertex of polyline: ("
39662 << prev_seg_boundary_id
39663 <<
") and\nfirst vertex of polyline (" << bound
39664 <<
").\nThis should have failed when first trying to "
39665 <<
"construct the\npolygon.\n";
39667 OOMPH_CURRENT_FUNCTION,
39668 OOMPH_EXCEPTION_LOCATION);
39675 std::reverse(vector_vertex_node.begin(),
39676 vector_vertex_node.end());
39689 std::ostringstream error_stream;
39691 <<
"The distance between the first node of the current\n"
39692 <<
"line segment (boundary " << bound
39693 <<
") and either end of "
39694 <<
"the previous line segment\n"
39695 <<
"(boundary " << prev_seg_boundary_id
39696 <<
") is bigger than the "
39697 <<
"desired tolerance "
39700 <<
"This suggests that the polylines defining the polygonal\n"
39701 <<
"representation are not properly ordered.\n"
39702 <<
"Fail on last vertex of polyline: ("
39703 << prev_seg_boundary_id <<
") and\nfirst vertex of polyline ("
39705 <<
"This should have failed when first trying to construct\n"
39706 <<
"the polygon.\n";
39708 OOMPH_CURRENT_FUNCTION,
39709 OOMPH_EXCEPTION_LOCATION);
39715 std::reverse(vector_vertex_node.begin(),
39716 vector_vertex_node.end());
39733 n_vertex = vector_vertex_node.size();
39745 double unrefinement_tolerance =
39749 double refinement_tolerance =
39760#ifdef OOMPH_HAS_MPI
39763 if (this->is_mesh_distributed())
39769 this->copy_connection_information(open_curve_pt->
polyline_pt(cs),
39770 tmp_curve_section_pt);
39778 this->copy_connection_information(open_curve_pt->
polyline_pt(cs),
39779 tmp_curve_section_pt);
39785 bool delete_it_on_destructor =
false;
39787 std::set<TriangleMeshCurveSection*>::iterator it =
39790 if (it != this->Free_curve_section_pt.end())
39792 this->Free_curve_section_pt.erase(it);
39794 delete_it_on_destructor =
true;
39802 this->Boundary_curve_section_pt[bound] =
39805 if (delete_it_on_destructor)
39810#ifdef OOMPH_HAS_MPI
39813 if (this->is_mesh_distributed() && nsub_boundaries == 1)
39816 this->Boundary_marked_as_shared_boundary[bound].clear();
39819 this->Boundary_marked_as_shared_boundary[bound].push_back(
39820 internal_to_shared_boundary[0]);
39824 else if (this->is_mesh_distributed() && nsub_boundaries > 1)
39830 this->Boundary_subpolylines[bound].clear();
39832 this->Boundary_subpolylines[bound].resize(nsub_boundaries);
39835 this->Boundary_marked_as_shared_boundary[bound].clear();
39838 this->Boundary_marked_as_shared_boundary[bound].resize(nsub_boundaries);
39839 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
39848 this->Boundary_subpolylines[bound][isub] = sub_tmp_polyline_pt;
39852 this->Boundary_marked_as_shared_boundary[bound][isub] =
39853 internal_to_shared_boundary[isub];
39863 sub_tmp_polyline_pt;
39864 this->copy_connection_information_to_sub_polylines(
39865 tmp_curve_section_pt, tmp_sub_curve_section_pt);
39875 delete mesh_geom_obj_pt;
39880 for (
unsigned p = 0; p < ncurve_section; p++)
39882 face_mesh_pt[p]->flush_node_storage();
39883 delete face_mesh_pt[p];
39886 return update_was_performed;
39889#ifdef OOMPH_HAS_MPI
39894 template<
class ELEMENT>
39901 unsigned update_was_performed =
false;
39904 const unsigned n_polylines = vector_polyline_pt.size();
39905 for (
unsigned pp = 0; pp < n_polylines; pp++)
39908 const unsigned shd_bnd_id = vector_polyline_pt[pp]->boundary_id();
39911 const unsigned chunk = vector_polyline_pt[pp]->boundary_chunk();
39919 std::map<FiniteElement*, FiniteElement*> face_ele_pt_to_bulk_element_pt;
39928 const unsigned nshared_bound_ele =
39929 this->nshared_boundary_element(shd_bnd_id);
39933 for (
unsigned e = 0;
e < nshared_bound_ele;
e++)
39937 this->shared_boundary_element_pt(shd_bnd_id,
e);
39940 int face_index = this->face_index_at_shared_boundary(shd_bnd_id,
e);
39949 face_ele_pt_to_bulk_element_pt[face_ele_pt] = bulk_ele_pt;
39955 nonhalo_shared_face_ele_pt.push_back(face_ele_pt);
39960 halo_shared_face_ele_pt.push_back(face_ele_pt);
39970 std::map<FiniteElement*, bool> shared_face_done;
39973 const unsigned nnonhalo_face_shared_ele =
39974 nonhalo_shared_face_ele_pt.size();
39977 const unsigned nhalo_face_shared_ele = halo_shared_face_ele_pt.size();
39982 if (nshared_bound_ele / 2 != nnonhalo_face_shared_ele)
39984 std::ostringstream error_message;
39986 <<
"The number of shared boundary elements (" << nshared_bound_ele
39987 <<
") is not the double\nof the number of unsorted NONHALO shared "
39988 <<
"face boundary elements (" << nnonhalo_face_shared_ele <<
")\n"
39989 <<
"for the current boundary (" << shd_bnd_id <<
")\n\n";
39991 OOMPH_CURRENT_FUNCTION,
39992 OOMPH_EXCEPTION_LOCATION);
39997 if (nshared_bound_ele / 2 != nhalo_face_shared_ele)
39999 std::ostringstream error_message;
40001 <<
"The number of shared boundary elements (" << nshared_bound_ele
40002 <<
") is not the double\nof the number of unsorted HALO shared "
40003 <<
"face boundary elements (" << nhalo_face_shared_ele <<
")\n"
40004 <<
"for the current boundary (" << shd_bnd_id <<
")\n\n";
40006 OOMPH_CURRENT_FUNCTION,
40007 OOMPH_EXCEPTION_LOCATION);
40014 for (
unsigned inh = 0; inh < nnonhalo_face_shared_ele; inh++)
40017 FiniteElement* nonhalo_face_ele_pt = nonhalo_shared_face_ele_pt[inh];
40020 const unsigned nnodes_nh = nonhalo_face_ele_pt->
nnode();
40022 Node* nh_first_node_pt = nonhalo_face_ele_pt->
node_pt(0);
40023 Node* nh_last_node_pt = nonhalo_face_ele_pt->
node_pt(nnodes_nh - 1);
40027 for (
unsigned ih = 0; ih < nhalo_face_shared_ele; ih++)
40030 FiniteElement* halo_face_ele_pt = halo_shared_face_ele_pt[ih];
40033 if (!shared_face_done[halo_face_ele_pt])
40036 const unsigned nnodes_h = halo_face_ele_pt->
nnode();
40038 Node* h_first_node_pt = halo_face_ele_pt->
node_pt(0);
40039 Node* h_last_node_pt = halo_face_ele_pt->
node_pt(nnodes_h - 1);
40043 if (nh_first_node_pt == h_first_node_pt &&
40044 nh_last_node_pt == h_last_node_pt)
40051 face_ele_pt_to_bulk_element_pt[nonhalo_face_ele_pt];
40053 face_ele_pt_to_bulk_element_pt[halo_face_ele_pt];
40056 tmp_bulk_element_pt.push_back(nonhalo_bulk_ele_pt);
40057 tmp_bulk_element_pt.push_back(halo_bulk_ele_pt);
40060 unsorted_shared_bulk_ele_pt.push_back(tmp_bulk_element_pt);
40063 shared_face_done[nonhalo_face_ele_pt] =
true;
40064 shared_face_done[halo_face_ele_pt] =
true;
40070 else if (nh_first_node_pt == h_last_node_pt &&
40071 nh_last_node_pt == h_first_node_pt)
40078 face_ele_pt_to_bulk_element_pt[nonhalo_face_ele_pt];
40080 face_ele_pt_to_bulk_element_pt[halo_face_ele_pt];
40083 tmp_bulk_element_pt.push_back(nonhalo_bulk_ele_pt);
40084 tmp_bulk_element_pt.push_back(halo_bulk_ele_pt);
40087 unsorted_shared_bulk_ele_pt.push_back(tmp_bulk_element_pt);
40090 shared_face_done[nonhalo_face_ele_pt] =
true;
40091 shared_face_done[halo_face_ele_pt] =
true;
40113 const unsigned nunsorted_shared_bulk_ele =
40114 unsorted_shared_bulk_ele_pt.size();
40118 if (nshared_bound_ele / 2 != nunsorted_shared_bulk_ele)
40120 std::ostringstream error_message;
40122 <<
"The number of shared boundary elements (" << nshared_bound_ele
40123 <<
") is not the double\nof the number of unsorted shared bulk "
40124 <<
"boundary elements (" << nunsorted_shared_bulk_ele <<
")\n"
40125 <<
"for the current boundary (" << shd_bnd_id <<
")\n\n";
40127 OOMPH_CURRENT_FUNCTION,
40128 OOMPH_EXCEPTION_LOCATION);
40133 if ((nnonhalo_face_shared_ele + nhalo_face_shared_ele) !=
40134 shared_face_done.size())
40136 std::ostringstream error_message;
40137 error_message <<
"The number of DONE shared boundary face elements ("
40138 << shared_face_done.size()
40139 <<
") is not the same\n as the sum of"
40140 <<
"the nonhalo face shared boundary elements ("
40141 << nnonhalo_face_shared_ele
40142 <<
")\nand the halo face shared "
40143 <<
"boundary elements (" << nhalo_face_shared_ele
40145 <<
"current boundary (" << shd_bnd_id <<
")\n\n";
40147 OOMPH_CURRENT_FUNCTION,
40148 OOMPH_EXCEPTION_LOCATION);
40153 shared_face_done.clear();
40156 unsigned nsorted_face_ele = 0;
40160 std::list<Node*> sorted_nodes;
40163 std::list<FiniteElement*> sorted_shared_bound_elements_pt;
40166 FiniteElement* root_face_ele_pt = nonhalo_shared_face_ele_pt[0];
40167 nsorted_face_ele++;
40170 shared_face_done[root_face_ele_pt] =
true;
40173 const unsigned nnodes_root = root_face_ele_pt->
nnode();
40174 Node* first_node_pt = root_face_ele_pt->
node_pt(0);
40175 Node* last_node_pt = root_face_ele_pt->
node_pt(nnodes_root - 1);
40178 sorted_nodes.push_back(first_node_pt);
40179 sorted_nodes.push_back(last_node_pt);
40182 sorted_shared_bound_elements_pt.push_back(
40183 unsorted_shared_bulk_ele_pt[0][0]);
40184 sorted_shared_bound_elements_pt.push_back(
40185 unsorted_shared_bulk_ele_pt[0][1]);
40188 while (nsorted_face_ele < nnonhalo_face_shared_ele)
40191 bool node_added =
false;
40195 for (
unsigned iface = 1; iface < nnonhalo_face_shared_ele; iface++)
40198 nonhalo_shared_face_ele_pt[iface];
40201 if (!shared_face_done[tmp_shared_face_ele_pt])
40204 const unsigned tmp_nnodes = tmp_shared_face_ele_pt->
nnode();
40207 Node* left_node_pt = tmp_shared_face_ele_pt->
node_pt(0);
40208 Node* right_node_pt =
40209 tmp_shared_face_ele_pt->
node_pt(tmp_nnodes - 1);
40211 if (left_node_pt == first_node_pt)
40214 sorted_nodes.push_front(right_node_pt);
40215 first_node_pt = right_node_pt;
40219 sorted_shared_bound_elements_pt.push_front(
40220 unsorted_shared_bulk_ele_pt[iface][1]);
40221 sorted_shared_bound_elements_pt.push_front(
40222 unsorted_shared_bulk_ele_pt[iface][0]);
40224 else if (left_node_pt == last_node_pt)
40227 sorted_nodes.push_back(right_node_pt);
40228 last_node_pt = right_node_pt;
40232 sorted_shared_bound_elements_pt.push_back(
40233 unsorted_shared_bulk_ele_pt[iface][0]);
40234 sorted_shared_bound_elements_pt.push_back(
40235 unsorted_shared_bulk_ele_pt[iface][1]);
40237 else if (right_node_pt == first_node_pt)
40240 sorted_nodes.push_front(left_node_pt);
40241 first_node_pt = left_node_pt;
40245 sorted_shared_bound_elements_pt.push_front(
40246 unsorted_shared_bulk_ele_pt[iface][1]);
40247 sorted_shared_bound_elements_pt.push_front(
40248 unsorted_shared_bulk_ele_pt[iface][0]);
40250 else if (right_node_pt == last_node_pt)
40253 sorted_nodes.push_back(left_node_pt);
40254 last_node_pt = left_node_pt;
40258 sorted_shared_bound_elements_pt.push_back(
40259 unsorted_shared_bulk_ele_pt[iface][0]);
40260 sorted_shared_bound_elements_pt.push_back(
40261 unsorted_shared_bulk_ele_pt[iface][1]);
40268 shared_face_done[tmp_shared_face_ele_pt] =
true;
40269 nsorted_face_ele++;
40286 for (
unsigned inh = 0; inh < nnonhalo_face_shared_ele; inh++)
40288 delete nonhalo_shared_face_ele_pt[inh];
40289 nonhalo_shared_face_ele_pt[inh] = 0;
40293 for (
unsigned ih = 0; ih < nhalo_face_shared_ele; ih++)
40295 delete halo_shared_face_ele_pt[ih];
40296 halo_shared_face_ele_pt[ih] = 0;
40304 const unsigned n_nodes = sorted_nodes.size();
40310 unsigned counter = 0;
40311 for (std::list<Node*>::iterator it_nodes = sorted_nodes.begin();
40312 it_nodes != sorted_nodes.end();
40315 polyline_vertices[counter].resize(2);
40316 polyline_vertices[counter][0] = (*it_nodes)->x(0);
40317 polyline_vertices[counter][1] = (*it_nodes)->x(1);
40327 for (std::list<FiniteElement*>::iterator it_ele =
40328 sorted_shared_bound_elements_pt.begin();
40329 it_ele != sorted_shared_bound_elements_pt.end();
40332 sorted_shared_ele_pt.push_back((*it_ele));
40336 const unsigned n_shared_target_areas = sorted_shared_ele_pt.size();
40337 Vector<double> sorted_shared_target_areas(n_shared_target_areas);
40340 std::map<std::pair<GeneralisedElement*, unsigned>,
bool> shared_ele_done;
40343 unsigned count_found_shared_element = 0;
40346 const unsigned nele = this->nelement();
40350 for (
unsigned e = 0;
e < nele;
e++)
40355 for (
unsigned s = 0;
s < n_shared_target_areas;
s++)
40360 std::pair<GeneralisedElement*, unsigned> pair_gen_ele_idx =
40361 std::make_pair(current_shared_ele_pt,
s);
40362 if (!shared_ele_done[pair_gen_ele_idx])
40365 if (current_ele_pt == current_shared_ele_pt)
40368 sorted_shared_target_areas[
s] = target_areas[
e];
40370 shared_ele_done[pair_gen_ele_idx] =
true;
40372 count_found_shared_element++;
40378 if (count_found_shared_element == n_shared_target_areas)
40388 if (count_found_shared_element != n_shared_target_areas)
40390 std::ostringstream error_message;
40391 error_message <<
"The number of found target areas ("
40392 << count_found_shared_element
40393 <<
") is different from the "
40394 <<
"total number\nof target areas ("
40395 << n_shared_target_areas <<
") in shared boundary ("
40396 << shd_bnd_id <<
")\n\n";
40398 OOMPH_CURRENT_FUNCTION,
40399 OOMPH_EXCEPTION_LOCATION);
40404 const unsigned n_vertices = n_nodes;
40407 const unsigned n_segments = vector_polyline_pt[pp]->nsegment();
40416 if (n_segments != n_vertices - 1)
40418 std::ostringstream error_message;
40420 <<
"The number of segments from the current shared polyline "
40421 <<
"(" << n_segments <<
") does not\ncorrespond with the number of "
40422 <<
"sorted vertices (" << n_vertices - 1
40423 <<
") of the current shared\n"
40426 OOMPH_CURRENT_FUNCTION,
40427 OOMPH_EXCEPTION_LOCATION);
40432 if (n_segments != n_shared_target_areas / 2)
40434 std::ostringstream error_message;
40436 <<
"The number of segments for the current sorting of edges "
40437 <<
"(" << n_segments <<
") is different\nfrom the number of "
40438 <<
"target areas (" << n_shared_target_areas / 2 <<
")\n\n";
40440 OOMPH_CURRENT_FUNCTION,
40441 OOMPH_EXCEPTION_LOCATION);
40455 for (
unsigned s = 0;
s < n_segments;
s++)
40458 polyline_target_area[
s] =
40459 std::min(sorted_shared_target_areas[
s * 2],
40460 sorted_shared_target_areas[(
s * 2) + 1]);
40467 if (polyline_vertices[n_vertices - 1][1] < polyline_vertices[0][1])
40469 std::reverse(polyline_vertices.begin(), polyline_vertices.end());
40470 std::reverse(polyline_target_area.begin(), polyline_target_area.end());
40472 else if (polyline_vertices[n_vertices - 1][1] == polyline_vertices[0][1])
40474 if (polyline_vertices[n_vertices - 1][0] < polyline_vertices[0][0])
40476 std::reverse(polyline_vertices.begin(), polyline_vertices.end());
40477 std::reverse(polyline_target_area.begin(),
40478 polyline_target_area.end());
40484 bool unrefinement_applied =
false;
40487 if (n_vertices > 3)
40489 unrefinement_applied =
40490 unrefine_shared_boundary_constrained_by_target_area(
40491 shd_bnd_id, chunk, polyline_vertices, polyline_target_area);
40495 bool refinement_applied =
40496 refine_shared_boundary_constrained_by_target_area(polyline_vertices,
40497 polyline_target_area);
40500 update_was_performed |= (unrefinement_applied || refinement_applied);
40514 this->copy_connection_information(curve_section_pt, new_polyline_pt);
40519 bool delete_it_on_destructor =
false;
40523 std::set<TriangleMeshCurveSection*>::iterator it =
40524 this->Free_curve_section_pt.find(curve_section_pt);
40526 if (it != this->Free_curve_section_pt.end())
40528 this->Free_curve_section_pt.erase(it);
40529 delete curve_section_pt;
40530 delete_it_on_destructor =
true;
40534 vector_polyline_pt[pp] = new_polyline_pt;
40540 this->Boundary_curve_section_pt[shd_bnd_id] = new_curve_section_pt;
40542 if (delete_it_on_destructor)
40544 this->Free_curve_section_pt.insert(new_curve_section_pt);
40549 return update_was_performed;
40558 template<
class ELEMENT>
40564 double& unrefinement_tolerance,
40568 std::set<Vector<double>> no_delete_vertex;
40571 const bool boundary_receive_connections =
40572 this->boundary_connections(b, c, no_delete_vertex);
40576 bool unrefinement_applied =
false;
40579 if (!Do_boundary_unrefinement_constrained_by_target_areas)
40581 return unrefinement_applied;
40595 unsigned n_vertex = vector_bnd_vertices.size();
40598 const double constant_value = 4.0 / sqrt(3.0);
40604 for (
unsigned i = 1;
i < n_vertex - 1;
i += 2)
40606 if (area_constraint[
i - 1] > 0 && area_constraint[
i] > 0)
40608 const double local_zeta_first = vector_bnd_vertices[
i - 1][0];
40609 const double local_zeta_last = vector_bnd_vertices[
i + 1][0];
40610 const double local_length_zeta =
40611 std::fabs(local_zeta_last - local_zeta_first);
40613 const double x1 = vector_bnd_vertices[
i - 1][1];
40614 const double y1 = vector_bnd_vertices[
i - 1][2];
40615 const double x2 = vector_bnd_vertices[
i + 1][1];
40616 const double y2 = vector_bnd_vertices[
i + 1][2];
40617 const double local_length =
40618 sqrt(((x1 - x2) * (x1 - x2)) + ((y1 - y2) * (y1 - y2)));
40620 const double x_m = vector_bnd_vertices[
i][1];
40621 const double y_m = vector_bnd_vertices[
i][2];
40623 const double average_area_constraint =
40624 (area_constraint[
i - 1] + area_constraint[
i]) / 2.0;
40628 const double length_side =
40629 sqrt(constant_value * average_area_constraint);
40631 const double length_side_zeta =
40632 (local_length_zeta * length_side) / local_length;
40635 if ((length_side_zeta / local_length_zeta) > 1.0)
40643 double a_x = vector_bnd_vertices[
i - 1][1];
40644 double a_y = vector_bnd_vertices[
i - 1][2];
40645 double b_x = vector_bnd_vertices[
i][1];
40646 double b_y = vector_bnd_vertices[
i][2];
40647 double c_x = vector_bnd_vertices[
i + 1][1];
40648 double c_y = vector_bnd_vertices[
i + 1][2];
40650 double a = b_x - a_x;
40651 double b = b_y - a_y;
40652 double c = c_x - a_x;
40653 double d = c_y - a_y;
40655 double e = a * (a_x + b_x) + b * (a_y + b_y);
40656 double f = c * (a_x + c_x) + d * (a_y + c_y);
40658 double g = 2.0 * (a * (c_y - b_y) - b * (c_x - b_x));
40660 bool do_it =
false;
40661 if (std::fabs(g) < 1.0e-14)
40667 double p_x = (d *
e - b *
f) / g;
40668 double p_y = (a *
f - c *
e) / g;
40670 double r = sqrt(pow((a_x - p_x), 2) + pow((a_y - p_y), 2));
40672 double rhalfca_x = 0.5 * (a_x - c_x);
40673 double rhalfca_y = 0.5 * (a_y - c_y);
40675 double halfca_squared = pow(rhalfca_x, 2) + pow(rhalfca_y, 2);
40677 double sticky_out_bit =
40678 r - sqrt(std::fabs((r * r) - halfca_squared));
40683 if ((sticky_out_bit / (2.0 * sqrt(halfca_squared))) <
40684 unrefinement_tolerance)
40692 if (do_it && boundary_receive_connections)
40696 no_delete_vertex.begin();
40697 it != no_delete_vertex.end();
40702 const double x = (*it)[0];
40703 const double y = (*it)[1];
40704 double error = (x_m -
x) * (x_m -
x) + (y_m - y) * (y_m - y);
40705 error = sqrt(error);
40721 vector_bnd_vertices[
i].resize(0);
40735 for (
unsigned i = 0;
i < n_vertex;
i++)
40738 if (vector_bnd_vertices[
i].size() != 0)
40740 compact_vector.push_back(vector_bnd_vertices[
i]);
40746 unsigned nsize_target = area_constraint.size();
40747 if (nsize_target == 1)
40750 compact_area_constraint.push_back(area_constraint[0]);
40754 for (
unsigned i = 1;
i < n_vertex;
i += 2)
40758 if (vector_bnd_vertices[
i].size() != 0)
40760 compact_area_constraint.push_back(area_constraint[
i - 1]);
40762 if (
i < nsize_target)
40764 compact_area_constraint.push_back(area_constraint[
i]);
40771 double new_area_constraint =
40772 (area_constraint[
i - 1] + area_constraint[
i]) / 2.0;
40773 compact_area_constraint.push_back(new_area_constraint);
40780 if (n_vertex != compact_vector.size())
40782 unrefinement_applied =
true;
40786 n_vertex = compact_vector.size();
40787 vector_bnd_vertices.resize(n_vertex);
40788 for (
unsigned i = 0;
i < n_vertex;
i++)
40790 vector_bnd_vertices[
i].resize(3);
40791 vector_bnd_vertices[
i][0] = compact_vector[
i][0];
40792 vector_bnd_vertices[
i][1] = compact_vector[
i][1];
40793 vector_bnd_vertices[
i][2] = compact_vector[
i][2];
40797 unsigned ntarget_areas = compact_area_constraint.size();
40798 area_constraint.resize(ntarget_areas);
40799 for (
unsigned i = 0;
i < ntarget_areas;
i++)
40801 area_constraint[
i] = compact_area_constraint[
i];
40806 return unrefinement_applied;
40814 template<
class ELEMENT>
40819 double& refinement_tolerance,
40824 bool refinement_applied =
false;
40827 if (!Do_boundary_refinement_constrained_by_target_areas)
40829 return refinement_applied;
40833 unsigned n_vertex = vector_bnd_vertices.size();
40836 const double constant_value = 4.0 / sqrt(3.0);
40846 for (
unsigned i = 0;
i < n_vertex - 1;
i++)
40849 new_vector.push_back(vector_bnd_vertices[
i]);
40851 if (area_constraint[
i] > 0)
40853 double local_zeta_first = vector_bnd_vertices[
i][0];
40854 double local_zeta_last = vector_bnd_vertices[
i + 1][0];
40855 const double local_length_zeta =
40856 std::fabs(local_zeta_last - local_zeta_first);
40861 if (local_zeta_first > local_zeta_last)
40863 const double tmp_zeta = local_zeta_first;
40864 local_zeta_first = local_zeta_last;
40865 local_zeta_last = tmp_zeta;
40868 const double x1 = vector_bnd_vertices[
i][1];
40869 const double y1 = vector_bnd_vertices[
i][2];
40870 const double x2 = vector_bnd_vertices[
i + 1][1];
40871 const double y2 = vector_bnd_vertices[
i + 1][2];
40872 const double local_length =
40873 sqrt(((x1 - x2) * (x1 - x2)) + ((y1 - y2) * (y1 - y2)));
40876 const double length_side = sqrt(constant_value * area_constraint[
i]);
40877 const double length_side_zeta =
40878 (local_length_zeta * length_side) / local_length;
40881 const double n_seg_double = length_side_zeta / local_length_zeta;
40884 unsigned n_seg = 1;
40887 n_seg +=
static_cast<unsigned>(std::floor(1.0 / n_seg_double));
40894 double zeta_increment = (local_length_zeta) / ((
double)n_seg);
40898 for (
unsigned s = 1;
s < n_seg;
s++)
40901 zeta[0] = local_zeta_first + zeta_increment * double(
s);
40903 mesh_geom_obj_pt->
position(zeta, vertex);
40907 new_node[0] = zeta[0];
40908 new_node[1] = vertex[0];
40909 new_node[2] = vertex[1];
40912 new_vector.push_back(new_node);
40923 new_vector.push_back(vector_bnd_vertices[n_vertex - 1]);
40928 n_vertex = new_vector.size();
40929 if (n_vertex != vector_bnd_vertices.size())
40931 refinement_applied =
true;
40935 vector_bnd_vertices.resize(n_vertex);
40936 for (
unsigned i = 0;
i < n_vertex;
i++)
40938 vector_bnd_vertices[
i].resize(3);
40939 vector_bnd_vertices[
i][0] = new_vector[
i][0];
40940 vector_bnd_vertices[
i][1] = new_vector[
i][1];
40941 vector_bnd_vertices[
i][2] = new_vector[
i][2];
40946 return refinement_applied;
40956 template<
class ELEMENT>
40965 std::set<Vector<double>> no_delete_vertex;
40968 const bool boundary_receive_connections =
40969 this->boundary_connections(b, c, no_delete_vertex);
40973 bool unrefinement_applied =
false;
40976 if (!Do_shared_boundary_unrefinement_constrained_by_target_areas)
40978 return unrefinement_applied;
40994 unsigned n_vertex = vector_bnd_vertices.size();
40997 const double constant_value = 4.0 / sqrt(3.0);
41003 for (
unsigned i = 1;
i < n_vertex - 1;
i += 2)
41007 if (area_constraint[
i - 1] > 0 && area_constraint[
i] > 0)
41010 const double x1 = vector_bnd_vertices[
i - 1][0];
41011 const double y1 = vector_bnd_vertices[
i - 1][1];
41013 const double x2 = vector_bnd_vertices[
i + 1][0];
41014 const double y2 = vector_bnd_vertices[
i + 1][1];
41017 const double local_length =
41018 sqrt(((x1 - x2) * (x1 - x2)) + ((y1 - y2) * (y1 - y2)));
41021 const double x_m = vector_bnd_vertices[
i][0];
41022 const double y_m = vector_bnd_vertices[
i][1];
41025 const double average_area_constraint =
41026 (area_constraint[
i - 1] + area_constraint[
i]) / 2.0;
41030 const double length_side =
41031 sqrt(constant_value * average_area_constraint);
41034 if ((length_side / local_length) > 1.0)
41040 if (do_it && boundary_receive_connections)
41044 no_delete_vertex.begin();
41045 it != no_delete_vertex.end();
41050 const double x = (*it)[0];
41051 const double y = (*it)[1];
41052 double error = (x_m -
x) * (x_m -
x) + (y_m - y) * (y_m - y);
41053 error = sqrt(error);
41069 vector_bnd_vertices[
i].resize(0);
41085 for (
unsigned i = 0;
i < n_vertex;
i++)
41088 if (vector_bnd_vertices[
i].size() != 0)
41090 compact_vector.push_back(vector_bnd_vertices[
i]);
41096 unsigned n_area_constraint = area_constraint.size();
41097 if (n_area_constraint == 1)
41100 compact_area_constraint.push_back(area_constraint[0]);
41104 for (
unsigned i = 1;
i < n_vertex;
i += 2)
41108 if (vector_bnd_vertices[
i].size() != 0)
41110 compact_area_constraint.push_back(area_constraint[
i - 1]);
41112 if (
i < n_area_constraint)
41114 compact_area_constraint.push_back(area_constraint[
i]);
41121 const double new_area_constraint =
41122 (area_constraint[
i - 1] + area_constraint[
i]) / 2.0;
41123 compact_area_constraint.push_back(new_area_constraint);
41130 if (n_vertex != compact_vector.size())
41132 unrefinement_applied =
true;
41136 n_vertex = compact_vector.size();
41137 vector_bnd_vertices.resize(n_vertex);
41138 for (
unsigned i = 0;
i < n_vertex;
i++)
41140 vector_bnd_vertices[
i].resize(2);
41141 vector_bnd_vertices[
i][0] = compact_vector[
i][0];
41142 vector_bnd_vertices[
i][1] = compact_vector[
i][1];
41146 unsigned ntarget_areas = compact_area_constraint.size();
41147 area_constraint.resize(ntarget_areas);
41148 for (
unsigned i = 0;
i < ntarget_areas;
i++)
41150 area_constraint[
i] = compact_area_constraint[
i];
41155 return unrefinement_applied;
41165 template<
class ELEMENT>
41173 bool refinement_applied =
false;
41176 if (!Do_shared_boundary_refinement_constrained_by_target_areas)
41178 return refinement_applied;
41182 unsigned nsegments = vector_bnd_vertices.size() - 1;
41189 const double constant_value = 4.0 / sqrt(3.0);
41191 for (
unsigned s = 0;
s < nsegments;
s++)
41197 const double x1 = left_vertex[0];
41198 const double y1 = left_vertex[1];
41199 const double x2 = right_vertex[0];
41200 const double y2 = right_vertex[1];
41203 const double segment_length =
41204 sqrt(((x1 - x2) * (x1 - x2)) + ((y1 - y2) * (y1 - y2)));
41207 const double new_segment_length =
41208 sqrt(constant_value * area_constraint[
s]);
41211 const double n_seg_double = new_segment_length / segment_length;
41216 nseg +=
static_cast<unsigned>(std::floor(1.0 / n_seg_double));
41220 tmp_bnd_vertices.push_back(left_vertex);
41227 double incrementx = (right_vertex[0] - left_vertex[0]) / (
double)(nseg);
41228 double incrementy = (right_vertex[1] - left_vertex[1]) / (
double)(nseg);
41229 for (
unsigned i = 1;
i < nseg;
i++)
41232 tmp_vertex[0] = left_vertex[0] + incrementx *
i;
41233 tmp_vertex[1] = left_vertex[1] + incrementy *
i;
41234 tmp_bnd_vertices.push_back(tmp_vertex);
41242 tmp_bnd_vertices.push_back(vector_bnd_vertices[nsegments]);
41247 nsegments = tmp_bnd_vertices.size() - 1;
41248 if (nsegments != vector_bnd_vertices.size() - 1)
41250 refinement_applied =
true;
41253 vector_bnd_vertices.resize(nsegments + 1);
41254 for (
unsigned i = 0;
i < nsegments + 1;
i++)
41256 vector_bnd_vertices[
i].resize(2);
41257 vector_bnd_vertices[
i][0] = tmp_bnd_vertices[
i][0];
41258 vector_bnd_vertices[
i][1] = tmp_bnd_vertices[
i][1];
41262 return refinement_applied;
41268 template<
class ELEMENT>
41279 get_face_mesh_representation(polygon_pt, face_mesh_pt);
41287 const unsigned n_polyline = polygon_pt->
npolyline();
41290 for (
unsigned p = 0; p < n_polyline; p++)
41304 std::set<Vector<double>> vertex_nodes;
41315#ifdef OOMPH_HAS_MPI
41342 const unsigned nface_element = face_mesh_pt[p]->nelement();
41348 std::map<FiniteElement*, unsigned> face_element_index_on_boundary;
41350 for (
unsigned ef = 0; ef < nface_element; ++ef)
41352 FiniteElement* ele_face_pt = face_mesh_pt[p]->finite_element_pt(ef);
41354#ifdef OOMPH_HAS_MPI
41355 if (this->is_mesh_distributed())
41365 non_halo_face_element_pt.push_back(ele_face_pt);
41366 face_element_index_on_boundary[ele_face_pt] = ef;
41370 const unsigned nnon_halo_face_element = non_halo_face_element_pt.size();
41373 std::map<FiniteElement*, bool> face_element_done;
41376 unsigned nsorted_face_elements = 0;
41378#ifdef OOMPH_HAS_MPI
41380 unsigned nsub_boundaries = 0;
41385 while (nsorted_face_elements < nnon_halo_face_element)
41390 bool found_initial_face_element =
false;
41393 unsigned iface = 0;
41394 for (iface = 0; iface < nnon_halo_face_element; iface++)
41396 ele_face_pt = non_halo_face_element_pt[iface];
41398 if (!face_element_done[ele_face_pt])
41401 found_initial_face_element =
true;
41403 nsorted_face_elements++;
41410 if (!found_initial_face_element)
41412 std::ostringstream error_message;
41413 error_message <<
"Could not find an initial face element for the "
41414 "current segment\n";
41417 error_message.str(),
41418 "RefineableTriangleMesh::update_polygon_after_restart()",
41419 OOMPH_EXCEPTION_LOCATION);
41426 std::set<Vector<double>> local_vertex_nodes;
41438 unsigned nnode = ele_face_pt->
nnode();
41441 ele_face_pt->
node_pt(0)->get_coordinates_on_boundary(bound, bound_left);
41442 vertex_coord[0] = bound_left[0];
41445 for (
unsigned i = 0;
i < 2;
i++)
41447 vertex_coord[
i + 1] = ele_face_pt->
node_pt(0)->x(
i);
41449 local_vertex_nodes.insert(vertex_coord);
41453 ele_face_pt->
node_pt(nnode - 1)->get_coordinates_on_boundary(
41454 bound, bound_right);
41455 vertex_coord[0] = bound_right[0];
41458 for (
unsigned i = 0;
i < 2;
i++)
41460 vertex_coord[
i + 1] = ele_face_pt->
node_pt(nnode - 1)->x(
i);
41462 local_vertex_nodes.insert(vertex_coord);
41465 Node* first_node_pt = ele_face_pt->
node_pt(0);
41466 Node* last_node_pt = ele_face_pt->
node_pt(nnode - 1);
41469 face_element_done[ele_face_pt] =
true;
41477 bool face_element_added =
false;
41486 for (
unsigned iiface = iface; iiface < nnon_halo_face_element;
41489 face_element_added =
false;
41490 ele_face_pt = non_halo_face_element_pt[iiface];
41491 if (!face_element_done[ele_face_pt])
41494 nnode = ele_face_pt->nnode();
41495 Node* left_node_pt = ele_face_pt->node_pt(0);
41496 Node* right_node_pt = ele_face_pt->node_pt(nnode - 1);
41498 if (left_node_pt == first_node_pt)
41500 first_node_pt = right_node_pt;
41501 face_element_added =
true;
41503 else if (left_node_pt == last_node_pt)
41505 last_node_pt = right_node_pt;
41506 face_element_added =
true;
41508 else if (right_node_pt == first_node_pt)
41510 first_node_pt = left_node_pt;
41511 face_element_added =
true;
41513 else if (right_node_pt == last_node_pt)
41515 last_node_pt = left_node_pt;
41516 face_element_added =
true;
41519 if (face_element_added)
41523 left_node_pt->get_coordinates_on_boundary(bound, bound_left);
41524 vertex_coord[0] = bound_left[0];
41527 for (
unsigned i = 0;
i < 2;
i++)
41529 vertex_coord[
i + 1] = left_node_pt->x(
i);
41531 local_vertex_nodes.insert(vertex_coord);
41535 right_node_pt->get_coordinates_on_boundary(bound, bound_right);
41536 vertex_coord[0] = bound_right[0];
41539 for (
unsigned i = 0;
i < 2;
i++)
41541 vertex_coord[
i + 1] = right_node_pt->x(
i);
41543 local_vertex_nodes.insert(vertex_coord);
41547 face_element_done[ele_face_pt] =
true;
41548 nsorted_face_elements++;
41555 }
while (face_element_added &&
41556 (nsorted_face_elements < nnon_halo_face_element));
41564 const unsigned nlocal_nodes = local_vertex_nodes.size();
41566 local_tmp_vector_vertex_node.resize(nlocal_nodes);
41569 unsigned counter = 0;
41570 std::set<Vector<double>>::iterator it_vertex;
41571 for (it_vertex = local_vertex_nodes.begin();
41572 it_vertex != local_vertex_nodes.end();
41575 local_tmp_vector_vertex_node[counter].resize(3);
41576 local_tmp_vector_vertex_node[counter][0] = (*it_vertex)[0];
41577 local_tmp_vector_vertex_node[counter][1] = (*it_vertex)[1];
41578 local_tmp_vector_vertex_node[counter][2] = (*it_vertex)[2];
41589 local_vertex_nodes.clear();
41594 unsigned nnew_nodes = local_tmp_vector_vertex_node.size();
41595 for (
unsigned i = 0;
i < nnew_nodes;
i++)
41597 vertex_coord[0] = local_tmp_vector_vertex_node[
i][0];
41598 vertex_coord[1] = local_tmp_vector_vertex_node[
i][1];
41599 vertex_coord[2] = local_tmp_vector_vertex_node[
i][2];
41600 vertex_nodes.insert(vertex_coord);
41601 local_vertex_nodes.insert(vertex_coord);
41604#ifdef OOMPH_HAS_MPI
41605 if (this->is_mesh_distributed())
41609 sub_vertex_nodes.push_back(local_vertex_nodes);
41618 unsigned npoly_vertex = vertex_nodes.size();
41619 tmp_vector_vertex_node.resize(npoly_vertex);
41620 unsigned count = 0;
41621 std::set<Vector<double>>::iterator it;
41622 for (it = vertex_nodes.begin(); it != vertex_nodes.end(); ++it)
41624 tmp_vector_vertex_node[count].resize(3);
41625 tmp_vector_vertex_node[count][0] = (*it)[0];
41626 tmp_vector_vertex_node[count][1] = (*it)[1];
41627 tmp_vector_vertex_node[count][2] = (*it)[2];
41631#ifdef OOMPH_HAS_MPI
41634 unsigned nsub_boundaries_set = sub_vertex_nodes.size();
41635 if (nsub_boundaries_set != nsub_boundaries)
41637 std::ostringstream error_message;
41639 <<
"The number of found sub-boundaries and the number of counted\n"
41640 <<
"sub-boundaries are different:\n"
41641 <<
"Number of found sub-boundaries: (" << nsub_boundaries_set <<
")\n"
41642 <<
"Number of counted sub-boundaries: (" << nsub_boundaries <<
")\n";
41644 error_message.str(),
41645 "RefineableTriangleMesh::update_polygon_after_restart()",
41646 OOMPH_EXCEPTION_LOCATION);
41651 if (this->is_mesh_distributed() && nsub_boundaries > 1)
41654 this->Boundary_was_splitted[bound] =
true;
41656 sub_tmp_vector_vertex_node.resize(nsub_boundaries);
41657 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
41660 const unsigned nsubpoly_vertex = sub_vertex_nodes[isub].size();
41661 sub_tmp_vector_vertex_node[isub].resize(nsubpoly_vertex);
41662 unsigned subcount = 0;
41663 std::set<Vector<double>>::iterator subit;
41664 for (subit = sub_vertex_nodes[isub].begin();
41665 subit != sub_vertex_nodes[isub].end();
41668 sub_tmp_vector_vertex_node[isub][subcount].resize(3);
41669 sub_tmp_vector_vertex_node[isub][subcount][0] = (*subit)[0];
41670 sub_tmp_vector_vertex_node[isub][subcount][1] = (*subit)[1];
41671 sub_tmp_vector_vertex_node[isub][subcount][2] = (*subit)[2];
41682 unsigned n_vertex = tmp_vector_vertex_node.size();
41685 vector_vertex_node.resize(n_vertex);
41686 for (
unsigned i = 0;
i < n_vertex;
i++)
41688 vector_vertex_node[
i].resize(2);
41689 vector_vertex_node[
i][0] = tmp_vector_vertex_node[
i][1];
41690 vector_vertex_node[
i][1] = tmp_vector_vertex_node[
i][2];
41693#ifdef OOMPH_HAS_MPI
41696 if (this->is_mesh_distributed() && nsub_boundaries > 1)
41701 sub_vector_vertex_node.resize(nsub_boundaries);
41702 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
41704 const unsigned subn_vertex = sub_tmp_vector_vertex_node[isub].size();
41706 sub_vector_vertex_node[isub].resize(subn_vertex);
41707 for (
unsigned i = 0;
i < subn_vertex;
i++)
41709 sub_vector_vertex_node[isub][
i].resize(2);
41710 sub_vector_vertex_node[isub][
i][0] =
41711 sub_tmp_vector_vertex_node[isub][
i][1];
41712 sub_vector_vertex_node[isub][
i][1] =
41713 sub_tmp_vector_vertex_node[isub][
i][2];
41728#ifdef OOMPH_HAS_MPI
41732 if (!this->is_mesh_distributed())
41739 unsigned n_prev_vertex =
41741 final_vertex_of_previous_segment =
41745 unsigned prev_seg_boundary_id =
41750 double error = 0.0;
41751 for (
unsigned i = 0;
i < 2;
i++)
41753 const double dist = final_vertex_of_previous_segment[
i] -
41754 (*vector_vertex_node.begin())[
i];
41755 error += dist * dist;
41757 error = sqrt(error);
41765 double rev_error = 0.0;
41766 for (
unsigned i = 0;
i < 2;
i++)
41768 const double dist = final_vertex_of_previous_segment[
i] -
41769 (*--vector_vertex_node.end())[
i];
41770 rev_error += dist * dist;
41772 rev_error = sqrt(rev_error);
41786 initial_vertex_of_previous_segment =
41789 unsigned prev_seg_boundary_id =
41794 double error = 0.0;
41795 for (
unsigned i = 0;
i < 2;
i++)
41797 const double dist = initial_vertex_of_previous_segment[
i] -
41798 (*vector_vertex_node.begin())[
i];
41799 error += dist * dist;
41801 error = sqrt(error);
41810 double rev_error = 0.0;
41811 for (
unsigned i = 0;
i < 2;
i++)
41813 const double dist = initial_vertex_of_previous_segment[
i] -
41814 (*--vector_vertex_node.end())[
i];
41815 rev_error += dist * dist;
41824 std::ostringstream error_stream;
41826 <<
"The distance between the first node of the current\n"
41827 <<
"line segment (boundary " << bound
41828 <<
") and either end of "
41829 <<
"the previous line segment\n"
41830 <<
"(boundary " << prev_seg_boundary_id
41831 <<
") is bigger than "
41832 <<
"the desired tolerance "
41835 <<
"This suggests that the polylines defining the "
41837 <<
"representation are not properly ordered.\n"
41838 <<
"Fail on last vertex of polyline: ("
41839 << prev_seg_boundary_id
41840 <<
") and\nfirst vertex of polyline (" << bound
41841 <<
").\nThis should have failed when first trying to"
41842 <<
" construct the\npolygon.\n";
41844 error_stream.str(),
41845 "RefineableTriangleMesh::update_polygon_after_restart()",
41846 OOMPH_EXCEPTION_LOCATION);
41853 std::reverse(vector_vertex_node.begin(),
41854 vector_vertex_node.end());
41867 std::ostringstream error_stream;
41869 <<
"The distance between the first node of the current\n"
41870 <<
"line segment (boundary " << bound
41871 <<
") and either end of "
41872 <<
"the previous line segment\n"
41873 <<
"(boundary " << prev_seg_boundary_id
41874 <<
") is bigger than the "
41875 <<
"desired tolerance "
41878 <<
"This suggests that the polylines defining the polygonal\n"
41879 <<
"representation are not properly ordered.\n"
41880 <<
"Fail on last vertex of polyline: ("
41881 << prev_seg_boundary_id <<
") and\nfirst vertex of polyline ("
41883 <<
"This should have failed when first trying to construct "
41887 error_stream.str(),
41888 "RefineableTriangleMesh::update_polygon_after_restart()",
41889 OOMPH_EXCEPTION_LOCATION);
41895 std::reverse(vector_vertex_node.begin(),
41896 vector_vertex_node.end());
41911 n_vertex = vector_vertex_node.size();
41931 double unrefinement_tolerance =
41935 double refinement_tolerance =
41950 this->copy_connection_information(polygon_pt->
polyline_pt(p),
41951 tmp_curve_section_pt);
41957 bool delete_it_on_destructor =
false;
41959 std::set<TriangleMeshCurveSection*>::iterator it =
41962 if (it != this->Free_curve_section_pt.end())
41964 this->Free_curve_section_pt.erase(it);
41966 delete_it_on_destructor =
true;
41974 this->Boundary_curve_section_pt[bound] =
41977 if (delete_it_on_destructor)
41982#ifdef OOMPH_HAS_MPI
41985 if (this->is_mesh_distributed() && nsub_boundaries > 1)
41990 this->Boundary_subpolylines[bound].clear();
41992 this->Boundary_subpolylines[bound].resize(nsub_boundaries);
41993 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
41999 sub_vector_vertex_node[isub], bound, isub);
42003 this->Boundary_subpolylines[bound][isub] = sub_tmp_polyline_pt;
42021 delete mesh_geom_obj_pt;
42026 for (
unsigned p = 0; p < n_polyline; p++)
42028 face_mesh_pt[p]->flush_node_storage();
42029 delete face_mesh_pt[p];
42037 template<
class ELEMENT>
42048 get_face_mesh_representation(open_curve_pt, face_mesh_pt);
42056 const unsigned ncurve_section = open_curve_pt->
ncurve_section();
42058 for (
unsigned cs = 0; cs < ncurve_section; cs++)
42079 const unsigned nface_element = face_mesh_pt[cs]->nelement();
42086 std::map<FiniteElement*, unsigned> face_element_index_on_boundary;
42089 std::map<FiniteElement*, bool> face_element_done;
42091 for (
unsigned ef = 0; ef < nface_element; ++ef)
42093 FiniteElement* ele_face_pt = face_mesh_pt[cs]->finite_element_pt(ef);
42098#ifdef OOMPH_HAS_MPI
42099 if (this->is_mesh_distributed())
42110 if (!face_element_done[ele_face_pt])
42115 non_halo_doubled_face_element_pt.push_back(ele_face_pt);
42117 face_element_index_on_boundary[ele_face_pt] = ef;
42119 face_element_done[ele_face_pt] =
true;
42121 const unsigned nnodes = ele_face_pt->
nnode();
42124 Node* left_node_pt = ele_face_pt->
node_pt(0);
42125 Node* right_node_pt = ele_face_pt->
node_pt(nnodes - 1);
42130 bool found_other_side_face_ele =
false;
42132 for (
unsigned iface = 0; iface < nface_element; iface++)
42136 face_mesh_pt[cs]->finite_element_pt(iface);
42138 if (!face_element_done[cele_face_pt])
42140 Node* cleft_node_pt = cele_face_pt->
node_pt(0);
42141 Node* cright_node_pt = cele_face_pt->
node_pt(nnodes - 1);
42144 if ((left_node_pt == cleft_node_pt &&
42145 right_node_pt == cright_node_pt) ||
42146 (left_node_pt == cright_node_pt &&
42147 right_node_pt == cleft_node_pt))
42150 non_halo_doubled_face_element_pt.push_back(cele_face_pt);
42152 face_element_done[cele_face_pt] =
true;
42154 face_element_index_on_boundary[cele_face_pt] = iface;
42157 found_other_side_face_ele =
true;
42165 if (!found_other_side_face_ele)
42167 std::ostringstream error_message;
42169 <<
"The face element at the other side of the boundary (" << bound
42170 <<
") was not found!!\n"
42171 <<
"These are the nodes of the face element:\n"
42172 <<
"(" << left_node_pt->x(0) <<
", " << left_node_pt->x(1) <<
") "
42173 <<
"and (" << right_node_pt->x(0) <<
"," << right_node_pt->x(1)
42176 error_message.str(),
42177 "RefineableTriangleMesh::update_open_curve_after_restart()",
42178 OOMPH_EXCEPTION_LOCATION);
42187 face_element_done.clear();
42192 std::set<Vector<double>> vertex_nodes;
42203#ifdef OOMPH_HAS_MPI
42208 std::vector<bool> internal_to_shared_boundary;
42233 unsigned nsorted_face_elements = 0;
42235#ifdef OOMPH_HAS_MPI
42237 unsigned nsub_boundaries = 0;
42241 const unsigned nnon_halo_doubled_face_ele =
42242 non_halo_doubled_face_element_pt.size();
42246 while (nsorted_face_elements < nnon_halo_doubled_face_ele)
42252 bool found_initial_face_element =
false;
42258 bool both_root_face_elements_are_nonhalo =
false;
42260 unsigned iface = 0;
42261 for (iface = 0; iface < nnon_halo_doubled_face_ele; iface += 2)
42263 ele_face_pt = non_halo_doubled_face_element_pt[iface];
42265 if (!face_element_done[ele_face_pt])
42268 face_element_done[ele_face_pt] =
true;
42270 repeated_ele_face_pt = non_halo_doubled_face_element_pt[iface + 1];
42272 face_element_done[repeated_ele_face_pt] =
true;
42274#ifdef OOMPH_HAS_MPI
42275 if (!repeated_ele_face_pt->
is_halo())
42277 both_root_face_elements_are_nonhalo =
true;
42283 nsorted_face_elements += 2;
42287 found_initial_face_element =
true;
42294 if (!found_initial_face_element)
42296 std::ostringstream error_message;
42297 error_message <<
"Could not find an initial face element for the "
42298 "current segment\n";
42301 OOMPH_CURRENT_FUNCTION,
42302 OOMPH_EXCEPTION_LOCATION);
42309 std::set<Vector<double>> local_vertex_nodes;
42321 const unsigned nnode = ele_face_pt->
nnode();
42324 ele_face_pt->
node_pt(0)->get_coordinates_on_boundary(bound, bound_left);
42325 vertex_coord[0] = bound_left[0];
42328 for (
unsigned i = 0;
i < 2;
i++)
42330 vertex_coord[
i + 1] = ele_face_pt->
node_pt(0)->x(
i);
42332 local_vertex_nodes.insert(vertex_coord);
42336 ele_face_pt->
node_pt(nnode - 1)->get_coordinates_on_boundary(
42337 bound, bound_right);
42338 vertex_coord[0] = bound_right[0];
42341 for (
unsigned i = 0;
i < 2;
i++)
42343 vertex_coord[
i + 1] = ele_face_pt->
node_pt(nnode - 1)->x(
i);
42345 local_vertex_nodes.insert(vertex_coord);
42348 Node* first_node_pt = ele_face_pt->
node_pt(0);
42349 Node* last_node_pt = ele_face_pt->
node_pt(nnode - 1);
42353 bool face_element_added =
false;
42363 for (
unsigned iiface = iface; iiface < nnon_halo_doubled_face_ele;
42366 face_element_added =
false;
42367 ele_face_pt = non_halo_doubled_face_element_pt[iiface];
42374 repeated_ele_face_pt = non_halo_doubled_face_element_pt[iiface + 1];
42375 bool both_face_elements_are_nonhalo =
false;
42377#ifdef OOMPH_HAS_MPI
42378 if (!repeated_ele_face_pt->
is_halo())
42380 both_face_elements_are_nonhalo =
true;
42384 if (!face_element_done[ele_face_pt] &&
42385 (both_face_elements_are_nonhalo ==
42386 both_root_face_elements_are_nonhalo))
42389 const unsigned nlnode = ele_face_pt->
nnode();
42390 Node* left_node_pt = ele_face_pt->
node_pt(0);
42391 Node* right_node_pt = ele_face_pt->
node_pt(nlnode - 1);
42393 if (left_node_pt == first_node_pt)
42395 first_node_pt = right_node_pt;
42396 face_element_added =
true;
42398 else if (left_node_pt == last_node_pt)
42400 last_node_pt = right_node_pt;
42401 face_element_added =
true;
42403 else if (right_node_pt == first_node_pt)
42405 first_node_pt = left_node_pt;
42406 face_element_added =
true;
42408 else if (right_node_pt == last_node_pt)
42410 last_node_pt = left_node_pt;
42411 face_element_added =
true;
42414 if (face_element_added)
42418 left_node_pt->get_coordinates_on_boundary(bound, bound_left);
42419 vertex_coord[0] = bound_left[0];
42422 for (
unsigned i = 0;
i < 2;
i++)
42424 vertex_coord[
i + 1] = left_node_pt->x(
i);
42426 local_vertex_nodes.insert(vertex_coord);
42430 right_node_pt->get_coordinates_on_boundary(bound, bound_right);
42431 vertex_coord[0] = bound_right[0];
42434 for (
unsigned i = 0;
i < 2;
i++)
42436 vertex_coord[
i + 1] = right_node_pt->x(
i);
42438 local_vertex_nodes.insert(vertex_coord);
42442 face_element_done[ele_face_pt] =
true;
42445 repeated_ele_face_pt =
42446 non_halo_doubled_face_element_pt[iiface + 1];
42447 face_element_done[repeated_ele_face_pt] =
true;
42449 nsorted_face_elements += 2;
42456 }
while (face_element_added &&
42457 (nsorted_face_elements < nnon_halo_doubled_face_ele));
42465 const unsigned nlocal_nodes = local_vertex_nodes.size();
42467 local_tmp_vector_vertex_node.resize(nlocal_nodes);
42470 unsigned counter = 0;
42471 std::set<Vector<double>>::iterator it_vertex;
42472 for (it_vertex = local_vertex_nodes.begin();
42473 it_vertex != local_vertex_nodes.end();
42476 local_tmp_vector_vertex_node[counter].resize(3);
42477 local_tmp_vector_vertex_node[counter][0] = (*it_vertex)[0];
42478 local_tmp_vector_vertex_node[counter][1] = (*it_vertex)[1];
42479 local_tmp_vector_vertex_node[counter][2] = (*it_vertex)[2];
42486 if (local_tmp_vector_vertex_node[nlocal_nodes - 1][2] <
42487 local_tmp_vector_vertex_node[0][2])
42489 std::reverse(local_tmp_vector_vertex_node.begin(),
42490 local_tmp_vector_vertex_node.end());
42492 else if (local_tmp_vector_vertex_node[nlocal_nodes - 1][2] ==
42493 local_tmp_vector_vertex_node[0][2])
42495 if (local_tmp_vector_vertex_node[nlocal_nodes - 1][1] <
42496 local_tmp_vector_vertex_node[0][1])
42498 std::reverse(local_tmp_vector_vertex_node.begin(),
42499 local_tmp_vector_vertex_node.end());
42510 local_vertex_nodes.clear();
42515 const unsigned nnew_nodes = local_tmp_vector_vertex_node.size();
42516 for (
unsigned i = 0;
i < nnew_nodes;
i++)
42518 vertex_coord[0] = local_tmp_vector_vertex_node[
i][0];
42519 vertex_coord[1] = local_tmp_vector_vertex_node[
i][1];
42520 vertex_coord[2] = local_tmp_vector_vertex_node[
i][2];
42521 vertex_nodes.insert(vertex_coord);
42522 local_vertex_nodes.insert(vertex_coord);
42525#ifdef OOMPH_HAS_MPI
42526 if (this->is_mesh_distributed())
42531 sub_vertex_nodes.push_back(local_vertex_nodes);
42537 if (both_root_face_elements_are_nonhalo)
42539 internal_to_shared_boundary.push_back(
false);
42543 internal_to_shared_boundary.push_back(
true);
42554 const unsigned npoly_vertex = vertex_nodes.size();
42555 tmp_vector_vertex_node.resize(npoly_vertex);
42556 unsigned count = 0;
42557 std::set<Vector<double>>::iterator it;
42558 for (it = vertex_nodes.begin(); it != vertex_nodes.end(); ++it)
42560 tmp_vector_vertex_node[count].resize(3);
42561 tmp_vector_vertex_node[count][0] = (*it)[0];
42562 tmp_vector_vertex_node[count][1] = (*it)[1];
42563 tmp_vector_vertex_node[count][2] = (*it)[2];
42567#ifdef OOMPH_HAS_MPI
42572 const unsigned nsub_boundaries_set = sub_vertex_nodes.size();
42573 const unsigned ninternal_to_shared_boundaries =
42574 internal_to_shared_boundary.size();
42575 if (nsub_boundaries_set != ninternal_to_shared_boundaries)
42577 std::ostringstream error_message;
42579 <<
"The number of found sub-boundaries and the number of marked "
42580 <<
"internal\nboundaries are different\n"
42581 <<
"Number of found sub-boundaries: (" << nsub_boundaries_set <<
")\n"
42582 <<
"Number of marked internal boundaries: ("
42583 << ninternal_to_shared_boundaries <<
")\n\n";
42585 error_message.str(),
42586 "RefineableTriangleMesh::update_open_curve_after_restart()",
42587 OOMPH_EXCEPTION_LOCATION);
42593 if (nsub_boundaries_set != nsub_boundaries)
42595 std::ostringstream error_message;
42597 <<
"The number of found sub-boundaries and the number of counted\n"
42598 <<
"sub-boundaries are different:\n"
42599 <<
"Number of found sub-boundaries: (" << nsub_boundaries_set <<
")\n"
42600 <<
"Number of counted sub-boundaries: (" << nsub_boundaries
42603 error_message.str(),
42604 "RefineableTriangleMesh::update_open_curve_after_restart()",
42605 OOMPH_EXCEPTION_LOCATION);
42610 if (this->is_mesh_distributed() && nsub_boundaries > 1)
42613 this->Boundary_was_splitted[bound] =
true;
42615 sub_tmp_vector_vertex_node.resize(nsub_boundaries);
42616 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
42619 const unsigned nsubpoly_vertex = sub_vertex_nodes[isub].size();
42620 sub_tmp_vector_vertex_node[isub].resize(nsubpoly_vertex);
42621 unsigned subcount = 0;
42622 std::set<Vector<double>>::iterator subit;
42623 for (subit = sub_vertex_nodes[isub].begin();
42624 subit != sub_vertex_nodes[isub].end();
42627 sub_tmp_vector_vertex_node[isub][subcount].resize(3);
42628 sub_tmp_vector_vertex_node[isub][subcount][0] = (*subit)[0];
42629 sub_tmp_vector_vertex_node[isub][subcount][1] = (*subit)[1];
42630 sub_tmp_vector_vertex_node[isub][subcount][2] = (*subit)[2];
42640 unsigned n_vertex = tmp_vector_vertex_node.size();
42643 vector_vertex_node.resize(n_vertex);
42644 for (
unsigned i = 0;
i < n_vertex;
i++)
42646 vector_vertex_node[
i].resize(2);
42647 vector_vertex_node[
i][0] = tmp_vector_vertex_node[
i][1];
42648 vector_vertex_node[
i][1] = tmp_vector_vertex_node[
i][2];
42651#ifdef OOMPH_HAS_MPI
42654 if (this->is_mesh_distributed() && nsub_boundaries > 1)
42659 sub_vector_vertex_node.resize(nsub_boundaries);
42660 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
42662 const unsigned subn_vertex = sub_tmp_vector_vertex_node[isub].size();
42664 sub_vector_vertex_node[isub].resize(subn_vertex);
42665 for (
unsigned i = 0;
i < subn_vertex;
i++)
42667 sub_vector_vertex_node[isub][
i].resize(2);
42668 sub_vector_vertex_node[isub][
i][0] =
42669 sub_tmp_vector_vertex_node[isub][
i][1];
42670 sub_vector_vertex_node[isub][
i][1] =
42671 sub_tmp_vector_vertex_node[isub][
i][2];
42686#ifdef OOMPH_HAS_MPI
42690 if (!this->is_mesh_distributed())
42697 unsigned n_prev_vertex =
42699 final_vertex_of_previous_segment =
42701 n_prev_vertex - 1);
42703 unsigned prev_seg_boundary_id =
42708 double error = 0.0;
42709 for (
unsigned i = 0;
i < 2;
i++)
42711 const double dist = final_vertex_of_previous_segment[
i] -
42712 (*vector_vertex_node.begin())[
i];
42713 error += dist * dist;
42715 error = sqrt(error);
42723 double rev_error = 0.0;
42724 for (
unsigned i = 0;
i < 2;
i++)
42726 const double dist = final_vertex_of_previous_segment[
i] -
42727 (*--vector_vertex_node.end())[
i];
42728 rev_error += dist * dist;
42730 rev_error = sqrt(rev_error);
42744 initial_vertex_of_previous_segment =
42747 unsigned prev_seg_boundary_id =
42752 double error = 0.0;
42753 for (
unsigned i = 0;
i < 2;
i++)
42755 const double dist = initial_vertex_of_previous_segment[
i] -
42756 (*vector_vertex_node.begin())[
i];
42757 error += dist * dist;
42759 error = sqrt(error);
42768 double rev_error = 0.0;
42769 for (
unsigned i = 0;
i < 2;
i++)
42771 const double dist = initial_vertex_of_previous_segment[
i] -
42772 (*--vector_vertex_node.end())[
i];
42773 rev_error += dist * dist;
42775 rev_error = sqrt(rev_error);
42781 std::ostringstream error_stream;
42783 <<
"The distance between the first node of the current\n"
42784 <<
"line segment (boundary " << bound
42785 <<
") and either end of "
42786 <<
"the previous line segment\n"
42787 <<
"(boundary " << prev_seg_boundary_id
42788 <<
") is bigger than"
42789 <<
" the desired tolerance "
42792 <<
"This suggests that the polylines defining the "
42794 <<
"representation are not properly ordered.\n"
42795 <<
"Fail on last vertex of polyline: ("
42796 << prev_seg_boundary_id
42797 <<
") and\nfirst vertex of polyline (" << bound
42798 <<
").\nThis should have failed when first trying to "
42799 <<
"construct the\npolygon.\n";
42801 "RefineableTriangleMesh::update_open_"
42802 "curve_after_restart()",
42803 OOMPH_EXCEPTION_LOCATION);
42810 std::reverse(vector_vertex_node.begin(),
42811 vector_vertex_node.end());
42824 std::ostringstream error_stream;
42826 <<
"The distance between the first node of the current\n"
42827 <<
"line segment (boundary " << bound
42828 <<
") and either end of "
42829 <<
"the previous line segment\n"
42830 <<
"(boundary " << prev_seg_boundary_id
42831 <<
") is bigger than the "
42832 <<
"desired tolerance "
42835 <<
"This suggests that the polylines defining the polygonal\n"
42836 <<
"representation are not properly ordered.\n"
42837 <<
"Fail on last vertex of polyline: ("
42838 << prev_seg_boundary_id <<
") and\nfirst vertex of polyline ("
42840 <<
"This should have failed when first trying to construct "
42844 error_stream.str(),
42845 "RefineableTriangleMesh::update_open_curve_after_restart()",
42846 OOMPH_EXCEPTION_LOCATION);
42852 std::reverse(vector_vertex_node.begin(),
42853 vector_vertex_node.end());
42871 n_vertex = vector_vertex_node.size();
42884 double unrefinement_tolerance =
42888 double refinement_tolerance =
42896 double maximum_length =
42904 this->copy_connection_information(open_curve_pt->
polyline_pt(cs),
42905 tmp_curve_section_pt);
42911 bool delete_it_on_destructor =
false;
42913 std::set<TriangleMeshCurveSection*>::iterator it =
42916 if (it != this->Free_curve_section_pt.end())
42918 this->Free_curve_section_pt.erase(it);
42920 delete_it_on_destructor =
true;
42928 this->Boundary_curve_section_pt[bound] =
42931 if (delete_it_on_destructor)
42933 this->Free_curve_section_pt.insert(
42937#ifdef OOMPH_HAS_MPI
42941 if (this->is_mesh_distributed() && nsub_boundaries == 1)
42944 this->Boundary_marked_as_shared_boundary[bound].clear();
42947 this->Boundary_marked_as_shared_boundary[bound].push_back(
42948 internal_to_shared_boundary[0]);
42952 else if (this->is_mesh_distributed() && nsub_boundaries > 1)
42957 this->Boundary_subpolylines[bound].clear();
42959 this->Boundary_subpolylines[bound].resize(nsub_boundaries);
42962 this->Boundary_marked_as_shared_boundary[bound].clear();
42965 this->Boundary_marked_as_shared_boundary[bound].resize(
42967 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
42973 sub_vector_vertex_node[isub], bound, isub);
42977 this->Boundary_subpolylines[bound][isub] = sub_tmp_polyline_pt;
42981 this->Boundary_marked_as_shared_boundary[bound][isub] =
42982 internal_to_shared_boundary[isub];
42997 delete mesh_geom_obj_pt;
43002 for (
unsigned p = 0; p < ncurve_section; p++)
43004 face_mesh_pt[p]->flush_node_storage();
43005 delete face_mesh_pt[p];
43009#ifdef OOMPH_HAS_MPI
43013 template<
class ELEMENT>
43018 const unsigned npolylines = vector_polyline_pt.size();
43019 for (
unsigned pp = 0; pp < npolylines; pp++)
43022 const unsigned b = vector_polyline_pt[pp]->boundary_id();
43027 std::map<std::pair<Node*, Node*>,
FiniteElement*> halo_edge_element_pt;
43028 std::map<std::pair<Node*, Node*>,
FiniteElement*> nonhalo_edge_element_pt;
43035 const unsigned nshared_bound_ele = this->nshared_boundary_element(b);
43036 for (
unsigned e = 0;
e < nshared_bound_ele;
e++)
43039 FiniteElement* current_ele_pt = this->shared_boundary_element_pt(b,
e);
43042 Node* first_node_pt = current_ele_pt->
node_pt(0);
43043 Node* second_node_pt = current_ele_pt->
node_pt(1);
43044 Node* third_node_pt = current_ele_pt->
node_pt(2);
43047 if (!current_ele_pt->
is_halo())
43050 nonhalo_edge_nodes_pt.push_back(first_node_pt);
43051 nonhalo_edge_nodes_pt.push_back(second_node_pt);
43053 nonhalo_edge_nodes_pt.push_back(second_node_pt);
43054 nonhalo_edge_nodes_pt.push_back(third_node_pt);
43056 nonhalo_edge_nodes_pt.push_back(third_node_pt);
43057 nonhalo_edge_nodes_pt.push_back(first_node_pt);
43060 std::pair<Node*, Node*> edge1 =
43061 std::make_pair(first_node_pt, second_node_pt);
43062 nonhalo_edge_element_pt[edge1] = current_ele_pt;
43064 std::pair<Node*, Node*> edge2 =
43065 std::make_pair(second_node_pt, third_node_pt);
43066 nonhalo_edge_element_pt[edge2] = current_ele_pt;
43068 std::pair<Node*, Node*> edge3 =
43069 std::make_pair(third_node_pt, first_node_pt);
43070 nonhalo_edge_element_pt[edge3] = current_ele_pt;
43075 halo_edge_nodes_pt.push_back(first_node_pt);
43076 halo_edge_nodes_pt.push_back(second_node_pt);
43078 halo_edge_nodes_pt.push_back(second_node_pt);
43079 halo_edge_nodes_pt.push_back(third_node_pt);
43081 halo_edge_nodes_pt.push_back(third_node_pt);
43082 halo_edge_nodes_pt.push_back(first_node_pt);
43085 std::pair<Node*, Node*> edge1 =
43086 std::make_pair(first_node_pt, second_node_pt);
43087 halo_edge_element_pt[edge1] = current_ele_pt;
43089 std::pair<Node*, Node*> edge2 =
43090 std::make_pair(second_node_pt, third_node_pt);
43091 halo_edge_element_pt[edge2] = current_ele_pt;
43093 std::pair<Node*, Node*> edge3 =
43094 std::make_pair(third_node_pt, first_node_pt);
43095 halo_edge_element_pt[edge3] = current_ele_pt;
43103 std::map<std::pair<Node*, Node*>,
bool> edge_done;
43112 const unsigned nnonhalo_edge_nodes = nonhalo_edge_nodes_pt.size();
43113 for (
unsigned i = 0;
i < nnonhalo_edge_nodes;
i += 2)
43116 currenti_edge[0] = nonhalo_edge_nodes_pt[
i];
43117 currenti_edge[1] = nonhalo_edge_nodes_pt[
i + 1];
43120 std::pair<Node*, Node*> new_edge =
43121 std::make_pair(currenti_edge[0], currenti_edge[1]);
43123 if (!edge_done[new_edge])
43125 const unsigned nhalo_edge_nodes = halo_edge_nodes_pt.size();
43126 for (
unsigned j = 0; j < nhalo_edge_nodes; j += 2)
43129 currentj_edge[0] = halo_edge_nodes_pt[j];
43130 currentj_edge[1] = halo_edge_nodes_pt[j + 1];
43133 if (currenti_edge[0] == currentj_edge[0] &&
43134 currenti_edge[1] == currentj_edge[1])
43137 unsorted_edges.push_back(new_edge);
43142 FiniteElement* nonhalo_ele_pt = nonhalo_edge_element_pt[new_edge];
43143 FiniteElement* halo_ele_pt = halo_edge_element_pt[new_edge];
43145 tmp_edge_element_pt.push_back(nonhalo_ele_pt);
43146 tmp_edge_element_pt.push_back(halo_ele_pt);
43149 unsorted_edges_elements_pt.push_back(tmp_edge_element_pt);
43152 edge_done[new_edge] =
true;
43160 else if (currenti_edge[0] == currentj_edge[1] &&
43161 currenti_edge[1] == currentj_edge[0])
43164 std::pair<Node*, Node*> new_edge =
43165 std::make_pair(currenti_edge[0], currenti_edge[1]);
43168 unsorted_edges.push_back(new_edge);
43171 std::pair<Node*, Node*> rev_new_edge =
43172 std::make_pair(currentj_edge[0], currentj_edge[1]);
43177 FiniteElement* nonhalo_ele_pt = nonhalo_edge_element_pt[new_edge];
43178 FiniteElement* halo_ele_pt = halo_edge_element_pt[rev_new_edge];
43180 tmp_edge_element_pt.push_back(nonhalo_ele_pt);
43181 tmp_edge_element_pt.push_back(halo_ele_pt);
43184 unsorted_edges_elements_pt.push_back(tmp_edge_element_pt);
43187 edge_done[new_edge] =
true;
43205 std::map<std::pair<Node*, Node*>,
bool> edge_sorted;
43207 const unsigned nunsorted_edges = unsorted_edges.size();
43212 if (nshared_bound_ele / 2 != nunsorted_edges)
43214 std::ostringstream error_message;
43216 <<
"The number of shared boundary elements (" << nshared_bound_ele
43217 <<
") is not the double\nof the number of unsorted edges ("
43218 << nunsorted_edges <<
") for the current boundary (" << b <<
")\n\n";
43220 error_message.str(),
43221 "RefineableTriangleMesh::update_shared_curve_after_restart()",
43222 OOMPH_EXCEPTION_LOCATION);
43226 unsigned nsorted_edges = 0;
43230 std::list<Node*> sorted_nodes;
43233 std::list<FiniteElement*> sorted_edges_elements_pt;
43236 std::pair<Node*, Node*> edge = unsorted_edges[0];
43240 edge_sorted[edge] =
true;
43243 Node* first_node_pt = edge.first;
43244 Node* last_node_pt = edge.second;
43247 sorted_nodes.push_back(first_node_pt);
43248 sorted_nodes.push_back(last_node_pt);
43251 sorted_edges_elements_pt.push_back(unsorted_edges_elements_pt[0][0]);
43252 sorted_edges_elements_pt.push_back(unsorted_edges_elements_pt[0][1]);
43256 while (nsorted_edges < nunsorted_edges)
43259 bool node_added =
false;
43263 for (
unsigned iedge = 1; iedge < nunsorted_edges; iedge++)
43265 edge = unsorted_edges[iedge];
43268 if (!edge_sorted[edge])
43271 Node* left_node_pt = edge.first;
43272 Node* right_node_pt = edge.second;
43274 if (left_node_pt == first_node_pt)
43277 sorted_nodes.push_front(right_node_pt);
43278 first_node_pt = right_node_pt;
43282 sorted_edges_elements_pt.push_front(
43283 unsorted_edges_elements_pt[iedge][1]);
43284 sorted_edges_elements_pt.push_front(
43285 unsorted_edges_elements_pt[iedge][0]);
43287 else if (left_node_pt == last_node_pt)
43290 sorted_nodes.push_back(right_node_pt);
43291 last_node_pt = right_node_pt;
43295 sorted_edges_elements_pt.push_back(
43296 unsorted_edges_elements_pt[iedge][0]);
43297 sorted_edges_elements_pt.push_back(
43298 unsorted_edges_elements_pt[iedge][1]);
43300 else if (right_node_pt == first_node_pt)
43303 sorted_nodes.push_front(left_node_pt);
43304 first_node_pt = left_node_pt;
43308 sorted_edges_elements_pt.push_front(
43309 unsorted_edges_elements_pt[iedge][1]);
43310 sorted_edges_elements_pt.push_front(
43311 unsorted_edges_elements_pt[iedge][0]);
43313 else if (right_node_pt == last_node_pt)
43316 sorted_nodes.push_back(left_node_pt);
43317 last_node_pt = left_node_pt;
43321 sorted_edges_elements_pt.push_back(
43322 unsorted_edges_elements_pt[iedge][0]);
43323 sorted_edges_elements_pt.push_back(
43324 unsorted_edges_elements_pt[iedge][1]);
43331 edge_sorted[edge] =
true;
43346 unsigned nvertex = sorted_nodes.size();
43351 unsigned counter = 0;
43352 for (std::list<Node*>::iterator it_nodes = sorted_nodes.begin();
43353 it_nodes != sorted_nodes.end();
43356 polyline_vertices[counter].resize(2);
43357 polyline_vertices[counter][0] = (*it_nodes)->x(0);
43358 polyline_vertices[counter][1] = (*it_nodes)->x(1);
43365 if (polyline_vertices[nvertex - 1][1] < polyline_vertices[0][1])
43367 std::reverse(polyline_vertices.begin(), polyline_vertices.end());
43369 else if (polyline_vertices[nvertex - 1][1] == polyline_vertices[0][1])
43371 if (polyline_vertices[nvertex - 1][0] < polyline_vertices[0][0])
43373 std::reverse(polyline_vertices.begin(), polyline_vertices.end());
43386 this->copy_connection_information(curve_section_pt, new_polyline_pt);
43391 bool delete_it_on_destructor =
false;
43395 std::set<TriangleMeshCurveSection*>::iterator it =
43396 this->Free_curve_section_pt.find(curve_section_pt);
43398 if (it != this->Free_curve_section_pt.end())
43400 this->Free_curve_section_pt.erase(it);
43401 delete curve_section_pt;
43402 delete_it_on_destructor =
true;
43406 vector_polyline_pt[pp] = new_polyline_pt;
43412 this->Boundary_curve_section_pt[b] = new_curve_section_pt;
43414 if (delete_it_on_destructor)
43416 this->Free_curve_section_pt.insert(new_curve_section_pt);
43428 template<
class ELEMENT>
43430 ELEMENT>::fill_boundary_elements_and_nodes_for_internal_boundaries()
43433 std::ofstream some_file;
43434 fill_boundary_elements_and_nodes_for_internal_boundaries(some_file);
43441 template<
class ELEMENT>
43444 std::ofstream& outfile)
43447 const unsigned nproc = this->communicator_pt()->nproc();
43449 unsigned my_rank = this->communicator_pt()->my_rank();
43452 std::map<unsigned, unsigned> shd_bnd_over_int_bnd =
43453 this->Shared_boundary_overlaps_internal_boundary;
43457 std::set<unsigned> internal_boundary_overlaped;
43461 if (outfile.is_open())
43463 const unsigned nbound = this->nboundary();
43464 outfile <<
"Number of boundaries: " << nbound <<
"\n\n";
43465 outfile <<
"Number of elements and nodes associated to each "
43466 <<
"boundary before\nfilling elements and nodes\n\n";
43467 for (
unsigned i = 0;
i < nbound;
i++)
43469 outfile <<
"Boundary (" <<
i <<
") Elements ("
43470 << this->nboundary_element(
i) <<
") "
43471 <<
"Nodes (" << this->nboundary_node(
i) <<
")\n";
43476 std::set<unsigned> shared_boundaries_in_this_processor;
43480 for (
unsigned iproc = 0; iproc < nproc; iproc++)
43483 if (iproc != my_rank)
43486 unsigned nshared_boundaries_with_iproc =
43487 this->nshared_boundaries(my_rank, iproc);
43489 if (nshared_boundaries_with_iproc > 0)
43493 bound_shared_with_iproc = this->shared_boundaries_ids(my_rank, iproc);
43496 for (
unsigned bs = 0; bs < nshared_boundaries_with_iproc; bs++)
43498 unsigned bnd_id = bound_shared_with_iproc[bs];
43499 shared_boundaries_in_this_processor.insert(bnd_id);
43510 for (std::map<unsigned, unsigned>::iterator it =
43511 shd_bnd_over_int_bnd.begin();
43512 it != shd_bnd_over_int_bnd.end();
43516 const unsigned shd_bnd_id = (*it).first;
43518 const unsigned int_bnd_id = (*it).second;
43521 std::set<unsigned>::iterator it_set =
43522 shared_boundaries_in_this_processor.find(shd_bnd_id);
43523 if (it_set != shared_boundaries_in_this_processor.end())
43525 internal_boundary_overlaped.insert(int_bnd_id);
43530 const unsigned nbnd_node_shd_bnd = this->nboundary_node(shd_bnd_id);
43534 if (outfile.is_open())
43536 outfile <<
"\nPass info. from shared (" << shd_bnd_id
43537 <<
") to internal (" << int_bnd_id <<
")\n";
43538 outfile <<
"Number of shared boundary nodes: " << nbnd_node_shd_bnd
43542 for (
unsigned in = 0; in < nbnd_node_shd_bnd; in++)
43545 Node* bnd_node_pt = this->boundary_node_pt(shd_bnd_id, in);
43547 this->add_boundary_node(int_bnd_id, bnd_node_pt);
43554 const unsigned nbnd_ele_shd_bnd = this->nboundary_element(shd_bnd_id);
43558 if (outfile.is_open())
43560 outfile <<
"Number of shared boundary elements: " << nbnd_ele_shd_bnd
43566 for (
unsigned ie = 0; ie < nbnd_ele_shd_bnd; ie++)
43569 FiniteElement* bnd_ele_pt = this->boundary_element_pt(shd_bnd_id, ie);
43572 Boundary_element_pt[int_bnd_id].push_back(bnd_ele_pt);
43574 int face_index = this->face_index_at_boundary(shd_bnd_id, ie);
43576 Face_index_at_boundary[int_bnd_id].push_back(face_index);
43581 const unsigned nregions = this->nregion();
43584 for (
unsigned ir = 0; ir < nregions; ir++)
43587 const unsigned region_id =
43588 static_cast<unsigned>(this->Region_attribute[ir]);
43591 const unsigned nele_ir =
43592 this->nboundary_element_in_region(shd_bnd_id, region_id);
43593 for (
unsigned ier = 0; ier < nele_ir; ier++)
43597 this->boundary_element_in_region_pt(shd_bnd_id, region_id, ier);
43600 this->Boundary_region_element_pt[int_bnd_id][region_id].push_back(
43604 int face_index = this->face_index_at_boundary_in_region(
43605 shd_bnd_id, region_id, ier);
43607 this->Face_index_region_at_boundary[int_bnd_id][region_id]
43608 .push_back(face_index);
43622 if (outfile.is_open())
43624 const unsigned nbound = this->nboundary();
43625 outfile <<
"Number of boundaries: " << nbound <<
"\n\n";
43626 outfile <<
"Number of elements and nodes associated to each "
43627 <<
"boundary after\nfilling elements and nodes\n\n";
43628 for (
unsigned i = 0;
i < nbound;
i++)
43630 outfile <<
"Boundary (" <<
i <<
") Elements ("
43631 << this->nboundary_element(
i) <<
")"
43632 <<
" Nodes (" << this->nboundary_node(
i) <<
")\n";
43640 for (std::set<unsigned>::iterator it = internal_boundary_overlaped.begin();
43641 it != internal_boundary_overlaped.end();
43644 const unsigned overlaped_internal_bnd_id = (*it);
43647 this->
template setup_boundary_coordinates<ELEMENT>(
43648 overlaped_internal_bnd_id);
43657 template<
class ELEMENT>
43662 if (!Boundary_coordinate_exists[b])
43679 std::set<Node*> tmp_boundary_node_pt;
43680 const unsigned nboundary_ele = this->nboundary_element(b);
43681 for (
unsigned e = 0;
e < nboundary_ele;
e++)
43685#ifdef OOMPH_HAS_MPI
43691 int face_index = this->face_index_at_boundary(b,
e);
43697 const unsigned nnodes = face_ele_pt->
nnode();
43698 for (
unsigned i = 0;
i < nnodes;
i++)
43701 Node* tmp_node_pt = face_ele_pt->
node_pt(
i);
43703 tmp_boundary_node_pt.insert(tmp_node_pt);
43707 delete face_ele_pt;
43709#ifdef OOMPH_HAS_MPI
43716 const unsigned long n_boundary_node = tmp_boundary_node_pt.
size();
43719 if (n_boundary_node == 0)
43721#ifdef OOMPH_HAS_MPI
43723 if (!this->is_mesh_distributed())
43727#ifdef OOMPH_HAS_MPI
43733 create_unsorted_face_mesh_representation(b, face_mesh_pt);
43737 delete mesh_geom_obj_pt;
43742 delete face_mesh_pt;
43754 unsigned tmp_counter = 0;
43755 for (std::set<Node*>::iterator it_node = tmp_boundary_node_pt.begin();
43756 it_node != tmp_boundary_node_pt.end();
43757 it_node++, tmp_counter++)
43759 Node* nod_pt = (*it_node);
43760 nod_pt->get_coordinates_on_boundary(b, b_coord);
43761 node_coord[0] = b_coord[0];
43762 node_coord[1] = nod_pt->x(0);
43763 node_coord[2] = nod_pt->x(1);
43764 old_boundary_node[tmp_counter] = node_coord;
43768 std::sort(old_boundary_node.begin(), old_boundary_node.end());
43779#ifdef OOMPH_HAS_MPI
43785 const unsigned nsegments = 1;
43788#ifdef OOMPH_HAS_MPI
43793 if (this->is_mesh_distributed())
43798 if (n_new_boundary_node == 0)
43802 create_unsorted_face_mesh_representation(b, face_mesh_pt);
43806 delete mesh_geom_obj_pt;
43810 delete face_mesh_pt;
43821 for (
unsigned is = 0; is < nsegments; is++)
43823#ifdef OOMPH_HAS_MPI
43824 const unsigned n_new_boundary_segment_node =
43827 const unsigned n_new_boundary_segment_node =
43833 node_coord.resize(6, 0.0);
43834 for (
unsigned n = 0; n < n_new_boundary_segment_node; n++)
43836#ifdef OOMPH_HAS_MPI
43841 nod_pt->get_coordinates_on_boundary(b, b_coord);
43842 node_coord[0] = b_coord[0];
43843 node_coord[1] = nod_pt->x(0);
43844 node_coord[2] = nod_pt->x(1);
43846 new_boundary_node[n] = node_coord;
43850 std::sort(new_boundary_node.begin(), new_boundary_node.end());
43857 unsigned old_index = 0;
43858 for (
unsigned n = 0; n < n_new_boundary_segment_node; ++n)
43862 for (
unsigned m = old_index; m < n_boundary_node; ++m)
43864 if ((std::fabs(old_boundary_node[m][1] - new_boundary_node[n][1]) <
43866 (std::fabs(old_boundary_node[m][2] - new_boundary_node[n][2]) <
43870 new_boundary_node[n][4] = old_boundary_node[m][0];
43872 new_boundary_node[n][5] = 1.0;
43883 if ((new_boundary_node[0][5] == 0.0) ||
43884 (new_boundary_node[n_new_boundary_segment_node - 1][5] == 0.0))
43886 std::ostringstream error_stream;
43888 <<
"New boundary coordinates not found for the first and/or last "
43890 <<
"on the boundary " << b <<
". This should not happen because "
43891 <<
"these\nlimits should have been setup in the constructor\n";
43893 <<
"The distance between the new and old nodes is probably outside\n"
43894 <<
"our tolerance.\n";
43895 error_stream.precision(20);
43896 error_stream <<
"Old boundaries: \n";
43897 error_stream << old_boundary_node[0][1] <<
" "
43898 << old_boundary_node[0][2] <<
" : "
43899 << old_boundary_node[n_boundary_node - 1][1] <<
" "
43900 << old_boundary_node[n_boundary_node - 1][2] <<
"\n";
43901 error_stream <<
"New boundaries: \n"
43902 << new_boundary_node[0][1] <<
" "
43903 << new_boundary_node[0][2] <<
" : "
43904 << new_boundary_node[n_new_boundary_segment_node - 1][1]
43906 << new_boundary_node[n_new_boundary_segment_node - 1][2]
43909 "RefineableTriangleMesh::snap_nodes_onto_boundary()",
43910 OOMPH_EXCEPTION_LOCATION);
43916 if (!this->is_mesh_distributed())
43920 new_boundary_node[0][4] = new_boundary_node[0][0];
43923 new_boundary_node[n_new_boundary_segment_node - 1][4] =
43924 new_boundary_node[0][5] = 1.0;
43926 new_boundary_node[n_new_boundary_segment_node - 1][4] =
43927 new_boundary_node[n_new_boundary_segment_node - 1][0];
43928 new_boundary_node[n_new_boundary_segment_node - 1][5] = 1.0;
43933 for (
unsigned n = 1; n < n_new_boundary_segment_node - 1; ++n)
43936 if (new_boundary_node[n][5] == 0.0)
43939 nodes_to_be_snapped[is].push_back(
43940 static_cast<unsigned>(new_boundary_node[n][3]));
43944 double zeta_old_low = new_boundary_node[n - 1][0];
43945 double zeta_new_low = new_boundary_node[n - 1][4];
43949 for (
unsigned m = n + 1; m < n_new_boundary_segment_node; ++m)
43951 if (new_boundary_node[m][5] == 1.0)
43954 double zeta_old_high = new_boundary_node[m][0];
43955 double zeta_new_high = new_boundary_node[m][4];
43957 double frac = (new_boundary_node[n][0] - zeta_old_low) /
43958 (zeta_old_high - zeta_old_low);
43959 new_boundary_node[n][4] =
43960 zeta_new_low +
frac * (zeta_new_high - zeta_new_low);
43961 new_boundary_node[n][5] = 1.0;
43969 for (
unsigned n = 0; n < n_new_boundary_segment_node; ++n)
43971 if (new_boundary_node[n][5] == 0)
43974 "New boundary coordinate not assigned\n",
43975 "RefineableTriangleMesh::snap_nodes_onto_boundary()",
43976 OOMPH_EXCEPTION_LOCATION);
43979#ifdef OOMPH_HAS_MPI
43983 b, is,
static_cast<unsigned>(new_boundary_node[n][3]))
43984 ->get_coordinates_on_boundary(b, b_coord);
43986 b_coord[0] = new_boundary_node[n][4];
43989 b, is,
static_cast<unsigned>(new_boundary_node[n][3]))
43990 ->set_coordinates_on_boundary(b, b_coord);
43995 ->get_coordinates_on_boundary(b, b_coord);
43997 b_coord[0] = new_boundary_node[n][4];
44000 ->set_coordinates_on_boundary(b, b_coord);
44007 create_unsorted_face_mesh_representation(b, face_mesh_pt);
44017 for (
unsigned is = 0; is < nsegments; is++)
44019 const unsigned nnodes_to_snap = nodes_to_be_snapped[is].size();
44021 for (
unsigned in = 0; in < nnodes_to_snap; in++)
44024 unsigned n = nodes_to_be_snapped[is][in];
44025#ifdef OOMPH_HAS_MPI
44033 nod_pt->get_coordinates_on_boundary(b, b_coord);
44035 mesh_geom_obj_pt->
position(b_coord, new_x);
44038 for (
unsigned i = 0;
i < 2;
i++)
44040 nod_pt->x(
i) = new_x[
i];
44046 delete mesh_geom_obj_pt;
44050 delete face_mesh_pt;
44057 for (
unsigned j = 0; j < 6; j++)
44059 dummy_six_node_element.construct_node(j);
44065 for (
unsigned e = 0;
e < n_bound_el;
e++)
44070 unsigned nnod = el_pt->
nnode();
44086 "Have a three-noded element that's not a TElement<2,2>",
44087 OOMPH_CURRENT_FUNCTION,
44088 OOMPH_EXCEPTION_LOCATION);
44096 else if ((nnod == 6) || (nnod == 7))
44106 "Have a six-noded element that's not a TElement<2,3>",
44107 OOMPH_CURRENT_FUNCTION,
44108 OOMPH_EXCEPTION_LOCATION);
44113 "Have a seven-noded element that's not a TElement<2,3>",
44114 OOMPH_CURRENT_FUNCTION,
44115 OOMPH_EXCEPTION_LOCATION);
44128 if (el_pt->
node_pt(3)->is_on_boundary(b))
44132 if (!el_pt->
node_pt(5)->is_on_boundary())
44135 for (
unsigned i = 0;
i < 2;
i++)
44143 if (!el_pt->
node_pt(4)->is_on_boundary())
44146 for (
unsigned i = 0;
i < 2;
i++)
44155 if (el_pt->
node_pt(4)->is_on_boundary(b))
44159 if (!el_pt->
node_pt(5)->is_on_boundary())
44162 for (
unsigned i = 0;
i < 2;
i++)
44170 if (!el_pt->
node_pt(3)->is_on_boundary())
44173 for (
unsigned i = 0;
i < 2;
i++)
44182 if (el_pt->
node_pt(5)->is_on_boundary(b))
44186 if (!el_pt->
node_pt(4)->is_on_boundary())
44189 for (
unsigned i = 0;
i < 2;
i++)
44197 if (!el_pt->
node_pt(3)->is_on_boundary())
44200 for (
unsigned i = 0;
i < 2;
i++)
44217 throw OomphLibError(
"Have seven-noded element that's not a "
44218 "TBubbleEnrichedElement<2,3>",
44219 OOMPH_CURRENT_FUNCTION,
44220 OOMPH_EXCEPTION_LOCATION);
44225 for (
unsigned j = 0; j < 6; j++)
44227 for (
unsigned i = 0;
i < 2;
i++)
44229 dummy_six_node_element.node_pt(j)->x(
i) = el_pt->
node_pt(j)->x(
i);
44234 unsigned j_enriched = 6;
44240 dummy_six_node_element.interpolated_x(
s,
x);
44241 el_pt->
node_pt(j_enriched)->x(0) =
x[0];
44242 el_pt->
node_pt(j_enriched)->x(1) =
x[1];
44249 std::ostringstream error_stream;
44250 error_stream <<
"Cannot deal with this particular " << nnod
44251 <<
"-noded element yet.\n"
44252 <<
"Please implement this yourself.\n";
44254 error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
44259 for (
unsigned j = 0; j < 6; j++)
44261 delete dummy_six_node_element.node_pt(j);
///////////////////////////////////////////////////////////////////// ///////////////////////////////...
///////////////////////////////////////////////////////////////////////////// ///////////////////////...
void get_bin(const Vector< double > &zeta, int &bin_number)
Get the number of the bin containing the specified coordinate. Bin number is negative if the coordina...
void fill_bin_by_diffusion(const unsigned &bin_diffusion_radius=1)
Fill bin by diffusion, populating each empty bin with the same content as the first non-empty bin fou...
const std::map< unsigned, Vector< std::pair< FiniteElement *, Vector< double > > > > * get_all_bins_content() const
Get the contents of all bins in vector.
void get_fill_stats(unsigned &n_bin, unsigned &max_n_entry, unsigned &min_n_entry, unsigned &tot_n_entry, unsigned &n_empty) const
Provide some stats on the fill level of the associated bin.
////////////////////////////////////////////////////////////////////
virtual void update_node_update(AlgebraicNode *&node_pt)=0
Update the node update info for given node, following mesh adaptation. Must be implemented for every ...
GeomObject * geom_object_list_pt(const unsigned &i)
Access function to the ith GeomObject.
unsigned ngeom_object_list_pt()
Return number of geometric objects associated with AlgebraicMesh.
////////////////////////////////////////////////////////////////////
unsigned ngeom_object(const int &id)
Number of geometric objects involved in id-th update function.
unsigned nref_value(const int &id)
Number of reference values involved in id-th update function.
GeomObject * geom_object_pt(const unsigned &i)
Return pointer to i-th geometric object involved in default (usually first) update function.
int node_update_fct_id()
Default (usually first if there are multiple ones) node update fct id.
double ref_value(const unsigned &i)
Return i-th reference value involved in default (usually first) update function.
void add_node_update_info(const int &id, AlgebraicMesh *mesh_pt, const Vector< GeomObject * > &geom_object_pt, const Vector< double > &ref_value, const bool &called_from_constructor=false)
Add algebraic update information for node: What's the ID of the mesh update function (typically used ...
Vector< unsigned > & dimensions_of_bin_array()
Number of bins in each coordinate direction.
A class that contains the information required by Nodes that are located on Mesh boundaries....
std::map< unsigned, unsigned > *& index_of_first_value_assigned_by_face_element_pt()
Return pointer to the map giving the index of the first face element value.
/////////////////////////////////////////////////////////////////////////// /////////////////////////...
A class that represents a collection of data; each Data object may contain many different individual ...
void set_value(const unsigned &i, const double &value_)
Set the i-th stored data value to specified value. The only reason that we require an explicit set fu...
unsigned nvalue() const
Return number of values stored in data object (incl pinned ones).
double value(const unsigned &i) const
Return i-th stored value. This function is not virtual so that it can be inlined. This means that if ...
Information for documentation of results: Directory and file number to enable output in the form RESL...
void disable_doc()
Disable documentation.
//////////////////////////////////////////////////////////////////// ////////////////////////////////...
Class that is used to create FaceElement from bulk elements and to provide these FaceElement with a g...
void set_boundary_number_in_bulk_mesh(const unsigned &b)
Set function for the boundary number in bulk mesh.
A general Finite Element class.
virtual void local_coordinate_of_node(const unsigned &j, Vector< double > &s) const
Get local coordinates of node j in the element; vector sets its own size (broken virtual)
virtual double interpolated_x(const Vector< double > &s, const unsigned &i) const
Return FE interpolated coordinate x[i] at local coordinate s.
double size() const
Calculate the size of the element (length, area, volume,...) in Eulerian computational coordinates....
virtual Node * construct_node(const unsigned &n)
Construct the local node n and return a pointer to the newly created node object.
unsigned nnode() const
Return the number of nodes.
virtual Node * construct_boundary_node(const unsigned &n)
Construct the local node n as a boundary node; that is a node that MAY be placed on a mesh boundary a...
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
A Generalised Element class.
bool is_halo() const
Is this element a halo?
int non_halo_proc_ID()
ID of processor ID that holds non-halo counterpart of halo element; negative if not a halo.
bool must_be_kept_as_halo() const
Test whether the element must be kept as a halo element.
Generalised timestepper that can serve a variety of purposes in continuation, bifurcation detection a...
/////////////////////////////////////////////////////////////////////
unsigned ndim() const
Access function to # of Eulerian coordinates.
MacroElementNodeUpdateMeshes contain MacroElementNodeUpdateNodes which have their own node update fun...
Vector< GeomObject * > geom_object_vector_pt()
Access function to the vector of GeomObject.
////////////////////////////////////////////////////////////////////
void set_node_update_info(FiniteElement *node_update_element_pt, const Vector< double > &s_in_node_update_element, const Vector< GeomObject * > &geom_object_pt)
Set node update information for node: Pass the pointer to the element that performs the update operat...
///////////////////////////////////////////////////////////////////// ///////////////////////////////...
SamplePointContainer * sample_point_container_pt() const
Pointer to the sample point container.
void position(const Vector< double > &zeta, Vector< double > &r) const
Return the position as a function of the intrinsic coordinate zeta. This provides an (expensive!...
unsigned long nboundary_node(const unsigned &ibound) const
Return number of nodes on a particular boundary.
void flush_element_and_node_storage()
Flush storage for elements and nodes by emptying the vectors that store the pointers to them....
FiniteElement * finite_element_pt(const unsigned &e) const
Upcast (downcast?) to FiniteElement (needed to access FiniteElement member functions).
int face_index_at_boundary(const unsigned &b, const unsigned &e) const
For the e-th finite element on boundary b, return int to indicate the face_index of the face adjacent...
unsigned nboundary_element(const unsigned &b) const
Return number of finite elements that are adjacent to boundary b.
Node *& node_pt(const unsigned long &n)
Return pointer to global node n.
void set_nodal_and_elemental_time_stepper(TimeStepper *const &time_stepper_pt, const bool &preserve_existing_data)
Set the timestepper associated with all nodal and elemental data stored in the mesh.
FiniteElement * boundary_element_pt(const unsigned &b, const unsigned &e) const
Return pointer to e-th finite element on boundary b.
unsigned nboundary() const
Return number of boundaries.
unsigned long nnode() const
Return number of nodes in the mesh.
GeneralisedElement *& element_pt(const unsigned long &e)
Return pointer to element e.
void add_element_pt(GeneralisedElement *const &element_pt)
Add a (pointer to) an element to the mesh.
void flush_node_storage()
Flush storage for nodes (only) by emptying the vectors that store the pointers to them.
unsigned long nelement() const
Return number of elements in the mesh.
Node *& boundary_node_pt(const unsigned &b, const unsigned &n)
Return pointer to node n on boundary b.
/////////////////////////////////////////////////////////////////////////// /////////////////////////...
An oomph-lib wrapper to the MPI_Comm communicator object. Just contains an MPI_Comm object (which is ...
An OomphLibError object which should be thrown when an run-time error is encountered....
An OomphLibWarning object which should be created as a temporary object to issue a warning....
void enable_problem_distributed()
Enable problem distributed.
void add_time_stepper_pt(TimeStepper *const &time_stepper_pt)
Add a timestepper to the problem. The function will automatically create or resize the Time object so...
Mesh *& mesh_pt()
Return a pointer to the global mesh.
Projection problem. This is created during the adaptation of unstructured meshes and it is assumed th...
void disable_use_iterative_solver_for_projection()
Disbales the use of an iterative solver for projection.
void project(Mesh *base_mesh_pt, const bool &dont_project_positions=false)
Project from base into the problem's own mesh.
///////////////////////////////////////////////////////////////////// ///////////////////////////////...
/////////////////////////////////////////////////////////////////// /////////////////////////////////...
void construct_new_halo_node_helper(Node *&new_nod_pt, Vector< Node * > &new_nodes_on_domain, Vector< Vector< Vector< std::map< unsigned, Node * > > > > &other_proc_shd_bnd_node_pt, unsigned &iproc, unsigned &node_index, FiniteElement *const &new_el_pt, Vector< Vector< Vector< unsigned > > > &global_node_names, std::map< Vector< unsigned >, unsigned > &node_name_to_global_index, Vector< Node * > &global_shared_node_pt)
Helper function which constructs a new halo node (on an element) with the information sent from the h...
void add_received_node_load_balance_helper(Node *&new_nod_pt, Vector< Vector< FiniteElement * > > &f_haloed_ele_pt, Vector< Vector< std::map< unsigned, FiniteElement * > > > &received_old_haloed_element_pt, Vector< Node * > &new_nodes_on_domain, Vector< Vector< Vector< std::map< unsigned, Node * > > > > &other_proc_shd_bnd_node_pt, unsigned &iproc, unsigned &node_index, FiniteElement *const &new_el_pt, Vector< Vector< Vector< unsigned > > > &global_node_names, std::map< Vector< unsigned >, unsigned > &node_name_to_global_index, Vector< Node * > &global_shared_node_pt)
Helper function to add a new node from load balance.
bool update_shared_curve_using_elements_area(Vector< TriangleMeshPolyLine * > &vector_polyline_pt, const Vector< double > &target_areas)
Updates the polylines using the elements area as constraint for the number of points along the bounda...
bool get_connected_vertex_number_on_dst_boundary(Vector< double > &vertex_coordinates, const unsigned &dst_b_id, unsigned &vertex_number)
Computes the associated vertex number on the destination boundary.
void send_boundary_node_info_of_shared_nodes(Vector< Vector< Vector< unsigned > > > &global_node_names, std::map< Vector< unsigned >, unsigned > &node_name_to_global_index, Vector< Node * > &global_shared_node_pt)
Get the original boundaries to which is associated each shared node, and send the info....
void update_shared_curve_after_restart(Vector< TriangleMeshPolyLine * > &vector_polyline_pt)
Updates the shared polylines representation after restart.
void send_and_receive_elements_nodes_info(int &send_proc, int &recv_proc)
Helper function to send back halo and haloed information.
void add_halo_node_helper(Node *&new_nod_pt, Vector< Node * > &new_nodes_on_domain, Vector< Vector< Vector< std::map< unsigned, Node * > > > > &other_proc_shd_bnd_node_pt, unsigned &iproc, unsigned &node_index, FiniteElement *const &new_el_pt, Vector< Vector< Vector< unsigned > > > &global_node_names, std::map< Vector< unsigned >, unsigned > &node_name_to_global_index, Vector< Node * > &global_shared_node_pt)
Helper function to add halo node.
double & max_element_size()
Max element size allowed during adaptation.
void snap_nodes_onto_boundary(RefineableTriangleMesh< ELEMENT > *&new_mesh_pt, const unsigned &b)
Snap the boundary nodes onto any curvilinear boundaries.
void reset_shared_boundary_elements_and_nodes(const bool flush_elements=true, const bool update_elements=true, const bool flush_nodes=true, const bool update_nodes=true)
Re-establish the shared boundary elements after the adaptation process (the updating of shared nodes ...
bool unrefine_shared_boundary_constrained_by_target_area(const unsigned &b, const unsigned &c, Vector< Vector< double > > &vector_bnd_vertices, Vector< double > &area_constraint)
Helper function that performs the unrefinement process on the specified boundary by using the provide...
void get_boundary_segment_nodes_helper(const unsigned &b, Vector< Vector< Node * > > &tmp_segment_nodes)
Get the nodes on the boundary (b), these are stored in the segment they belong (also used by the load...
bool unrefine_boundary(const unsigned &b, const unsigned &c, Vector< Vector< double > > &vector_bnd_vertices, double &unrefinement_tolerance, const bool &check_only=false)
Helper function that performs the unrefinement process.
void get_face_mesh_representation(TriangleMeshPolygon *polygon_pt, Vector< Mesh * > &face_mesh_pt)
Helper function to construct face mesh representation of all polylines, possibly with segments re-dis...
void add_non_delete_vertices_from_boundary_helper(Vector< Vector< Node * > > src_bound_segment_node_pt, Vector< Vector< Node * > > dst_bound_segment_node_pt, const unsigned &dst_bnd_id, const unsigned &dst_bnd_chunk)
Adds the vertices from the sources boundary that are repeated in the destination boundary to the list...
void add_node_load_balance_helper(unsigned &iproc, Vector< Vector< FiniteElement * > > &f_halo_ele_pt, Vector< Node * > &new_nodes_on_domain, Node *nod_pt)
Helper function to add haloed node.
void compute_shared_node_degree_helper(Vector< Vector< FiniteElement * > > &unsorted_face_ele_pt, std::map< Node *, unsigned > &global_node_degree)
Computes the degree of the nodes on the shared boundaries, the degree of the node is computed from th...
void resume_boundary_connections(Vector< TriangleMeshPolyLine * > &resume_initial_connection_polyline_pt, Vector< TriangleMeshPolyLine * > &resume_final_connection_polyline_pt)
Resume the boundary connections that may have been suspended because the destination boundary is no p...
void get_required_elemental_information_load_balance_helper(unsigned &iproc, Vector< Vector< FiniteElement * > > &f_haloed_ele_pt, FiniteElement *ele_pt)
Helper function to get the required elemental information from the element to be sent....
void sort_nodes_on_shared_boundaries()
Sort the nodes on shared boundaries so that the processors that share a boundary agree with the order...
double & min_element_size()
Min element size allowed during adaptation.
bool update_open_curve_using_elements_area(TriangleMeshOpenCurve *&open_curve_pt, const Vector< double > &target_area)
Updates the open curve but using the elements area instead of the default refinement and unrefinement...
void construct_new_node_load_balance_helper(Node *&new_nod_pt, Vector< Vector< FiniteElement * > > &f_haloed_ele_pt, Vector< Vector< std::map< unsigned, FiniteElement * > > > &received_old_haloed_element_pt, Vector< Node * > &new_nodes_on_domain, Vector< Vector< Vector< std::map< unsigned, Node * > > > > &other_proc_shd_bnd_node_pt, unsigned &iproc, unsigned &node_index, FiniteElement *const &new_el_pt, Vector< Vector< Vector< unsigned > > > &global_node_names, std::map< Vector< unsigned >, unsigned > &node_name_to_global_index, Vector< Node * > &global_shared_node_pt)
Helper function which constructs a new node (on an element) with the information sent from the load b...
void create_halo_element(unsigned &iproc, Vector< Node * > &new_nodes_on_domain, Vector< Vector< Vector< std::map< unsigned, Node * > > > > &other_proc_shd_bnd_node_pt, Vector< Vector< Vector< unsigned > > > &global_node_names, std::map< Vector< unsigned >, unsigned > &node_name_to_global_index, Vector< Node * > &global_shared_node_pt)
Helper function to create (halo) elements on the loop process based on the info received in send_and_...
void get_shared_boundary_elements_and_face_indexes(const Vector< FiniteElement * > &first_element_pt, const Vector< FiniteElement * > &second_element_pt, Vector< FiniteElement * > &first_shared_boundary_element_pt, Vector< unsigned > &first_shared_boundary_element_face_index, Vector< FiniteElement * > &second_shared_boundary_element_pt, Vector< unsigned > &second_shared_boundary_element_face_index)
Use the first and second group of elements to find the intersection between them to get the shared bo...
void create_sorted_face_mesh_representation(const unsigned &boundary_id, Mesh *face_mesh_pt, std::map< FiniteElement *, bool > &is_inverted, bool &inverted_face_mesh)
Helper function Creates a sorted face mesh representation of the specified PolyLine It means that the...
void update_open_curve_after_restart(TriangleMeshOpenCurve *&open_curve_pt)
Updates the open curve representation after restart.
void reset_halo_haloed_scheme()
In charge of. re-establish the halo(ed) scheme on all processors. Sends info. to create halo elements...
bool refine_boundary(Mesh *face_mesh_pt, Vector< Vector< double > > &vector_bnd_vertices, double &refinement_tolerance, const bool &check_only=false)
Helper function that performs the refinement process on the specified boundary by using the provided ...
void create_element_load_balance_helper(unsigned &iproc, Vector< Vector< FiniteElement * > > &f_haloed_ele_pt, Vector< Vector< std::map< unsigned, FiniteElement * > > > &received_old_haloed_element_pt, Vector< FiniteElement * > &new_elements_on_domain, Vector< Node * > &new_nodes_on_domain, Vector< Vector< Vector< std::map< unsigned, Node * > > > > &other_proc_shd_bnd_node_pt, Vector< Vector< Vector< unsigned > > > &global_node_names, std::map< Vector< unsigned >, unsigned > &node_name_to_global_index, Vector< Node * > &global_shared_node_pt)
Helper function to create elements on the loop process based on the info received in send_and_receive...
void create_new_shared_boundaries(std::set< FiniteElement * > &element_in_processor_pt, Vector< Vector< FiniteElement * > > &new_shared_boundary_element_pt, Vector< Vector< unsigned > > &new_shared_boundary_element_face_index)
Creates the new shared boundaries, this method is also in charge of computing the shared boundaries i...
void get_shared_boundary_segment_nodes_helper(const unsigned &shd_bnd_id, Vector< Vector< Node * > > &tmp_segment_nodes)
Get the nodes on the shared boundary (b), these are stored in the segment they belong.
void refine_triangulateio(TriangulateIO &triangulate_io, const Vector< double > &target_area, TriangulateIO &triangle_refine)
Build a new TriangulateIO object from previous TriangulateIO based on target area for each element.
void load_balance(const Vector< unsigned > &input_target_domain_for_local_non_halo_element)
Performs the load balancing for unstructured meshes, the load balancing strategy is based on mesh mig...
void create_unsorted_face_mesh_representation(const unsigned &boundary_id, Mesh *face_mesh_pt)
Helper function Creates an unsorted face mesh representation from the specified boundary id....
void add_element_load_balance_helper(const unsigned &iproc, Vector< Vector< std::map< unsigned, FiniteElement * > > > &received_old_haloed_element_pt, FiniteElement *ele_pt)
Helper function to create elements on the loop process based on the info received in send_and_receive...
void restore_boundary_connections(Vector< TriangleMeshPolyLine * > &resume_initial_connection_polyline_pt, Vector< TriangleMeshPolyLine * > &resume_final_connection_polyline_pt)
After unrefinement and refinement has taken place compute the new vertices numbers of the boundaries ...
bool update_open_curve_using_face_mesh(TriangleMeshOpenCurve *open_polyline_pt, const bool &check_only=false)
Helper function that updates the input open curve by using end-points of elements from FaceMesh(es) t...
bool apply_max_length_constraint(Mesh *face_mesh_pt, Vector< Vector< double > > &vector_bnd_vertices, double &max_length_constraint)
bool refine_boundary_constrained_by_target_area(MeshAsGeomObject *mesh_geom_obj_pt, Vector< Vector< double > > &vector_bnd_vertices, double &refinement_tolerance, Vector< double > &area_constraint)
Helper function that performs the refinement process on the specified boundary by using the provided ...
void create_temporary_boundary_connections(Vector< TriangleMeshPolygon * > &tmp_outer_polygons_pt, Vector< TriangleMeshOpenCurve * > &tmp_open_curves_pt)
After unrefinement and refinement has taken place compute the new vertices numbers of the temporary r...
void add_haloed_node_helper(unsigned &iproc, Node *nod_pt)
Helper function to add haloed node.
void get_required_nodal_information_helper(unsigned &iproc, Node *nod_pt)
Helper function to get the required nodal information from a haloed node so that a fully-functional h...
void compute_global_node_names_and_shared_nodes(Vector< Vector< Vector< std::map< unsigned, Node * > > > > &other_proc_shd_bnd_node_pt, Vector< Vector< Vector< unsigned > > > &global_node_names, std::map< Vector< unsigned >, unsigned > &node_name_to_global_index, Vector< Node * > &global_shared_node_pt)
Compute the names of the nodes on shared boundaries in this (my_rank) processor with other processors...
double & min_permitted_angle()
Min angle before remesh gets triggered.
void reset_halo_haloed_scheme_helper(Vector< Vector< Vector< std::map< unsigned, Node * > > > > &other_proc_shd_bnd_node_pt, Vector< Vector< Node * > > &iproc_currently_created_nodes_pt, Vector< Vector< Vector< unsigned > > > &global_node_names, std::map< Vector< unsigned >, unsigned > &node_name_to_global_index, Vector< Node * > &global_shared_node_pt)
In charge of creating additional halo(ed) elements on those processors that have no shared boundaries...
void get_required_nodal_information_load_balance_helper(Vector< Vector< FiniteElement * > > &f_halo_ele_pt, unsigned &iproc, Node *nod_pt)
Helper function to get the required nodal information from an haloed node so that a fully-functional ...
bool unrefine_boundary_constrained_by_target_area(const unsigned &b, const unsigned &c, Vector< Vector< double > > &vector_bnd_vertices, double &unrefinement_tolerance, Vector< double > &area_constraint)
Helper function that performs the unrefinement process on the specified boundary by using the provide...
void add_halo_element_helper(unsigned &iproc, FiniteElement *ele_pt)
Helper function to create (halo) elements on the loop process based on the info received in send_and_...
void update_other_proc_shd_bnd_node_helper(Node *&new_nod_pt, Vector< Vector< Vector< std::map< unsigned, Node * > > > > &other_proc_shd_bnd_node_pt, Vector< unsigned > &other_processor_1, Vector< unsigned > &other_processor_2, Vector< unsigned > &other_shared_boundaries, Vector< unsigned > &other_indexes, Vector< Vector< Vector< unsigned > > > &global_node_names, std::map< Vector< unsigned >, unsigned > &node_name_to_global_index, Vector< Node * > &global_shared_node_pt)
Helper function that assigns/updates the references to the node so that it can be found with any othe...
void create_adjacency_matrix_new_shared_edges_helper(Vector< Vector< FiniteElement * > > &unsorted_face_ele_pt, Vector< Vector< Node * > > &tmp_sorted_shared_node_pt, std::map< Node *, Vector< Vector< unsigned > > > &node_alias, Vector< Vector< Vector< unsigned > > > &adjacency_matrix)
Sort the nodes on the new shared boundaries (after load balancing), computes the alias of the nodes a...
void fill_boundary_elements_and_nodes_for_internal_boundaries()
bool refine_shared_boundary_constrained_by_target_area(Vector< Vector< double > > &vector_bnd_vertices, Vector< double > &area_constraint)
Helper function that performs the refinement process on the specified boundary by using the provided ...
bool update_polygon_using_face_mesh(TriangleMeshPolygon *polygon_pt, const bool &check_only=false)
Helper function that updates the input polygon's PSLG by using the end-points of elements from FaceMe...
void update_polygon_after_restart(TriangleMeshPolygon *&polygon_pt)
Updates the polylines representation after restart.
void add_vertices_for_non_deletion()
Mark the vertices that are not allowed for deletion by the unrefienment/refinement polyline methods....
void create_polylines_from_polyfiles(const std::string &node_file_name, const std::string &poly_file_name)
Helper function to create polylines and fill associate data.
bool update_polygon_using_elements_area(TriangleMeshPolygon *&polygon_pt, const Vector< double > &target_area)
Updates the polylines using the elements area as constraint for the number of points along the bounda...
void restore_polyline_connections_helper(TriangleMeshPolyLine *polyline_pt, Vector< TriangleMeshPolyLine * > &resume_initial_connection_polyline_pt, Vector< TriangleMeshPolyLine * > &resume_final_connection_polyline_pt)
Restore the connections of the specific polyline The vertices numbering on the destination boundaries...
void adapt(const Vector< double > &elem_error)
Adapt mesh, based on elemental error provided.
void enable_use_eulerian_coordinates_during_setup()
Enable use of eulerian coordinates (via interpolated_x) during setup (otherwise use interpolated_zeta...
A Class for nodes that deform elastically (i.e. position is an unknown in the problem)....
void add_values_to_vector(Vector< double > &vector_of_values)
Add all data, position and time history values to the vector Overload to add the Lagrangian coordinat...
Data *const & variable_position_pt() const
Pointer to variable_position data (const version)
void read_values_from_vector(const Vector< double > &vector_of_values, unsigned &index)
Read all data and time history values from the vector starting from index. On return the index will b...
////////////////////////////////////////////////////////////////////// //////////////////////////////...
unsigned ntstorage() const
Return the number of doubles required to represent history (one for steady)
Class to keep track of discrete/continous time. It is essential to have a single Time object when usi...
TriangulateIO & triangulateio_representation()
Access to the triangulateio representation of the mesh.
bool is_internal_point_fixed() const
Test whether the internal point is fixed.
Vector< double > internal_point() const
Coordinates of the internal point.
Base class for defining a triangle mesh boundary, this class has the methods that allow to connect th...
virtual unsigned boundary_chunk() const =0
Boundary chunk (Used when a boundary is represented by more than one polyline.
double unrefinement_tolerance()
Get tolerance for unrefinement of curve section to create a better representation of curvilinear boun...
void set_unrefinement_tolerance(const double &tolerance)
Set tolerance for unrefinement of curve sections to avoid unnecessarily large numbers of elements on ...
virtual unsigned boundary_id() const =0
Boundary id.
void connect_initial_vertex_to_polyline(TriangleMeshPolyLine *polyline_pt, const unsigned &vertex_number, const double &tolerance_for_connection=1.0e-14)
Connects the initial vertex of the curve section to a desired target polyline by specifying the verte...
void resume_initial_vertex_connected()
Resumes the initial vertex connection, it may be that after load balancing the boundary to which the ...
void suspend_final_vertex_connected()
Set the final vertex connection as suspended, it will be resumed when the method to resume the connec...
unsigned initial_vertex_connected_n_vertex() const
Gets the vertex number to which the initial end is connected.
void resume_final_vertex_connected()
Resumes the final vertex connection, it may be that after load balancing the boundary to which the co...
void set_refinement_tolerance(const double &tolerance)
Set tolerance for refinement of curve sections to create a better representation of curvilinear bound...
virtual unsigned nvertex() const =0
Number of vertices.
void connect_final_vertex_to_polyline(TriangleMeshPolyLine *polyline_pt, const unsigned &vertex_number, const double &tolerance_for_connection=1.0e-14)
Connects the final vertex of the curve section to a desired target polyline by specifying the vertex ...
unsigned final_vertex_connected_n_chunk() const
Gets the boundary chunk to which the final end is connected.
void set_maximum_length(const double &maximum_length)
Allows to specify the maximum distance between two vertices that define the associated polyline of th...
unsigned final_vertex_connected_n_vertex() const
Sets the vertex number to which the final end is connected.
double refinement_tolerance()
Get tolerance for refinement of curve sections to create a better representation of curvilinear bound...
bool is_final_vertex_connected() const
Test whether final vertex is connected or not.
unsigned initial_vertex_connected_bnd_id() const
Gets the id to which the initial end is connected.
bool is_initial_vertex_connected() const
Test whether initial vertex is connected or not.
void set_initial_vertex_connected()
Sets the initial vertex as connected.
void set_final_vertex_connected()
Sets the final vertex as connected.
void suspend_initial_vertex_connected()
Set the initial vertex connection as suspended, it will be resumed when the method to resume the conn...
unsigned initial_vertex_connected_n_chunk() const
Gets the boundary chunk to which the initial end is connected.
double maximum_length()
Gets access to the maximum length variable.
unsigned final_vertex_connected_bnd_id() const
Gets the id to which the final end is connected.
virtual TriangleMeshCurveSection * curve_section_pt(const unsigned &i) const
Pointer to i-th constituent curve section.
virtual unsigned ncurve_section() const
Number of constituent curves.
////////////////////////////////////////////////////////////////////// //////////////////////////////...
TriangleMeshPolyLine * polyline_pt(const unsigned &i) const
Pointer to i-th constituent polyline.
///////////////////////////////////////////////////////////////////// ///////////////////////////////...
void enable_use_attributes()
Helper function for enabling the use of attributes.
double element_area() const
Helper function for getting the element area.
void disable_automatic_creation_of_vertices_on_boundaries()
Disables the creation of points (by Triangle) on the outer and internal boundaries.
std::map< unsigned, Vector< double > > & regions_coordinates()
Helper function for getting access to the regions coordinates.
Vector< TriangleMeshClosedCurve * > internal_closed_curve_pt() const
Helper function for getting the internal closed boundaries.
Vector< Vector< double > > extra_holes_coordinates() const
Helper function for getting the extra holes.
void set_communicator_pt(OomphCommunicator *comm_pt)
Function to set communicator (mesh is then assumed to be distributed)
Vector< TriangleMeshOpenCurve * > internal_open_curves_pt() const
Helper function for getting the internal open boundaries.
Class defining a polyline for use in Triangle Mesh generation.
Vector< double > vertex_coordinate(const unsigned &i) const
Coordinate vector of i-th vertex (const version)
unsigned boundary_chunk() const
Boundary chunk (Used when a boundary is represented by more than one polyline.
void final_vertex_coordinate(Vector< double > &vertex)
Get last vertex coordinates.
unsigned nvertex() const
Number of vertices.
void reverse()
Reverse the polyline, this includes the connection information and the vertices order.
void initial_vertex_coordinate(Vector< double > &vertex)
Get first vertex coordinates.
unsigned boundary_id() const
Boundary id.
//////////////////////////////////////////////////////////////////// ////////////////////////////////...
unsigned npolyline() const
Number of constituent polylines.
bool can_update_reference_configuration() const
Test whether curve can update reference.
TriangleMeshPolyLine * polyline_pt(const unsigned &i) const
Pointer to i-th constituent polyline.
bool is_redistribution_of_segments_between_polylines_enabled()
Is re-distribution of polyline segments in the curve between different boundaries during adaptation e...
virtual void reset_reference_configuration()
Virtual function that should be overloaded to update the polygons reference configuration.
///////////////////////////////////////////////////////////////////// ///////////////////////////////...
const int check_connections_of_polyline_nodes(std::set< FiniteElement * > &element_in_processor_pt, const int &root_edge_bnd_id, std::map< std::pair< Node *, Node * >, bool > &overlapped_face, std::map< unsigned, std::map< Node *, bool > > &node_on_bnd_not_overlapped_by_shd_bnd, std::list< Node * > ¤t_polyline_nodes, std::map< unsigned, std::list< Node * > > &shared_bnd_id_to_sorted_list_node_pt, const unsigned &node_degree, Node *&new_node_pt, const bool called_from_load_balance=false)
Check for any possible connections that the array of sorted nodes have with any previous boundaries o...
void compute_boundary_segments_connectivity_and_initial_zeta_values(const unsigned &b)
Compute the boundary segments connectivity for those boundaries that were splited during the distribu...
void break_loops_on_shared_polyline_helper(const unsigned &initial_shd_bnd_id, std::list< Node * > &input_nodes, Vector< FiniteElement * > &input_boundary_element_pt, Vector< int > &input_face_index_element, const int &input_connect_to_the_left, const int &input_connect_to_the_right, Vector< std::list< Node * > > &output_sorted_nodes_pt, Vector< Vector< FiniteElement * > > &output_boundary_element_pt, Vector< Vector< int > > &output_face_index_element, Vector< int > &output_connect_to_the_left, Vector< int > &output_connect_to_the_right)
Break any possible loop created by the sorted list of nodes that is used to create a new shared polyl...
void build_triangulateio(const std::string &poly_file_name, TriangulateIO &triangulate_io, bool &use_attributes)
Helper function to create TriangulateIO object (return in triangulate_io) from the ....
void create_shared_boundaries(OomphCommunicator *comm_pt, const Vector< unsigned > &element_domain, const Vector< GeneralisedElement * > &backed_up_el_pt, const Vector< FiniteElement * > &backed_up_f_el_pt, std::map< Data *, std::set< unsigned > > &processors_associated_with_data, const bool &overrule_keep_as_halo_element_status)
Creates the shared boundaries.
Vector< unsigned > oomph_vertex_nodes_id()
Return the vector that contains the oomph-lib node number for all vertex nodes in the TriangulateIO r...
void create_shared_polylines_connections()
Establish the connections of the polylines previously marked as having connections....
void break_loops_on_shared_polyline_load_balance_helper(const unsigned &initial_shd_bnd_id, std::list< Node * > &input_nodes, Vector< FiniteElement * > &input_boundary_element_pt, Vector< FiniteElement * > &input_boundary_face_element_pt, Vector< int > &input_face_index_element, const int &input_connect_to_the_left, const int &input_connect_to_the_right, Vector< std::list< Node * > > &output_sorted_nodes_pt, Vector< Vector< FiniteElement * > > &output_boundary_element_pt, Vector< Vector< FiniteElement * > > &output_boundary_face_element_pt, Vector< Vector< int > > &output_face_index_element, Vector< int > &output_connect_to_the_left, Vector< int > &output_connect_to_the_right)
Break any possible loop created by the sorted list of nodes that is used to create a new shared polyl...
void synchronize_boundary_coordinates(const unsigned &b)
In charge of sinchronize the boundary coordinates for internal boundaries that were split as part of ...
void compute_holes_left_by_halo_elements_helper(Vector< Vector< double > > &output_holes_coordinates)
Compute the holes left by the halo elements, those adjacent to the shared boundaries.
void identify_boundary_segments_and_assign_initial_zeta_values(const unsigned &b, Vector< FiniteElement * > &input_face_ele_pt, const bool &is_internal_boundary, std::map< FiniteElement *, FiniteElement * > &face_to_bulk_element_pt)
Identify the segments from the old mesh (original mesh) in the new mesh (this) and assign initial and...
virtual void reset_boundary_element_info(Vector< unsigned > &ntmp_boundary_elements, Vector< Vector< unsigned > > &ntmp_boundary_elements_in_region, Vector< FiniteElement * > &deleted_elements)
Virtual function to perform the reset boundary elements info routines. Generally used after load bala...
const bool shared_boundary_overlaps_internal_boundary(const unsigned &shd_bnd_id)
Checks if the shared boundary overlaps an internal boundary.
Vector< Vector< Node * > > & boundary_segment_node_pt(const unsigned &b)
Return direct access to nodes associated with a boundary but sorted in segments.
Vector< Vector< Vector< unsigned > > > shared_boundaries_ids() const
void re_scale_re_assigned_initial_zeta_values_for_internal_boundary(const unsigned &b)
Re-scale the re-assigned zeta values for the boundary nodes, apply only for internal boundaries.
void create_shared_polyline(const unsigned &my_rank, const unsigned &shd_bnd_id, const unsigned &iproc, const unsigned &jproc, std::list< Node * > &sorted_nodes, const int &root_edge_bnd_id, Vector< FiniteElement * > &bulk_bnd_ele_pt, Vector< int > &face_index_ele, Vector< Vector< TriangleMeshPolyLine * > > &unsorted_polylines_pt, const int &connect_to_the_left_flag, const int &connect_to_the_right_flag)
Create the shared polyline and fill the data structured that keep all the information associated with...
void update_holes_information_helper(Vector< TriangleMeshPolygon * > &polygons_pt, Vector< Vector< double > > &output_holes_coordinates)
Keeps those vertices that define a hole, those that are inside closed internal boundaries in the new ...
void create_distributed_domain_representation(Vector< TriangleMeshPolygon * > &polygons_pt, Vector< TriangleMeshOpenCurve * > &open_curves_pt)
Creates the distributed domain representation. Joins the original boundaires, shared boundaries and c...
void build_from_scaffold(TimeStepper *time_stepper_pt, const bool &use_attributes)
Build mesh from scaffold.
void sort_polylines_helper(Vector< TriangleMeshPolyLine * > &unsorted_polylines_pt, Vector< Vector< TriangleMeshPolyLine * > > &sorted_polylines_pt)
Sorts the polylines so they be continuous and then we can create a closed or open curve from them.
void create_tmp_open_curves_helper(Vector< Vector< TriangleMeshPolyLine * > > &sorted_open_curves_pt, Vector< TriangleMeshPolyLine * > &unsorted_shared_to_internal_poly_pt, Vector< TriangleMeshOpenCurve * > &open_curves_pt)
Take the polylines from the original open curves and created new temporaly representations of open cu...
void get_halo_elements_on_all_procs(const unsigned &nproc, const Vector< unsigned > &element_domain, const Vector< GeneralisedElement * > &backed_up_el_pt, std::map< Data *, std::set< unsigned > > &processors_associated_with_data, const bool &overrule_keep_as_halo_element_status, std::map< GeneralisedElement *, unsigned > &element_to_global_index, Vector< Vector< Vector< GeneralisedElement * > > > &output_halo_elements_pt)
Creates the halo elements on all processors Gets the halo elements on all processors,...
void dump_distributed_info_for_restart(std::ostream &dump_file)
Used to dump info. related with distributed triangle meshes.
void re_assign_initial_zeta_values_for_internal_boundary(const unsigned &b, Vector< std::list< FiniteElement * > > &old_segment_sorted_ele_pt, std::map< FiniteElement *, bool > &old_is_inverted)
Re-assign the boundary segments initial zeta (arclength) value for those internal boundaries that wer...
void set_mesh_level_time_stepper(TimeStepper *const &time_stepper_pt, const bool &preserve_existing_data)
Overload set_mesh_level_time_stepper so that the stored time stepper now corresponds to the new times...
void read_distributed_info_for_restart(std::istream &restart_file)
Used to read info. related with distributed triangle meshes.
void select_boundary_face_elements(Vector< FiniteElement * > &face_el_pt, const unsigned &b, bool &is_internal_boundary, std::map< FiniteElement *, FiniteElement * > &face_to_bulk_element_pt)
Select face element from boundary using the criteria to decide which of the two face elements should ...
void create_polylines_from_halo_elements_helper(const Vector< unsigned > &element_domain, std::map< GeneralisedElement *, unsigned > &element_to_global_index, std::set< FiniteElement * > &element_in_processor_pt, Vector< Vector< Vector< GeneralisedElement * > > > &input_halo_elements, std::map< std::pair< Node *, Node * >, unsigned > &elements_edges_on_boundary, Vector< Vector< Vector< TriangleMeshPolyLine * > > > &output_polylines_pt)
Creates polylines from the intersection of halo elements on all processors. The new polylines define ...
void output_boundary_coordinates(const unsigned &b, std::ostream &outfile)
Output the nodes on the boundary and their respective boundary coordinates(into separate tecplot zone...
void create_tmp_polygons_helper(Vector< Vector< TriangleMeshPolyLine * > > &polylines_pt, Vector< TriangleMeshPolygon * > &polygons_pt)
Take the polylines from the shared boundaries and create temporary polygon representations of the dom...
void get_element_edges_on_boundary(std::map< std::pair< Node *, Node * >, unsigned > &element_edges_on_boundary)
Get the element edges (pair of nodes, edges) that lie on a boundary (used to mark shared boundaries t...
std::map< unsigned, Vector< double > > & boundary_segment_final_arclength()
Return direct access to the final arclength for the segments that are part of a boundary.
std::map< unsigned, Vector< double > > & boundary_segment_initial_zeta()
Return direct access to the initial zeta for the segments that are part of a boundary.
GeomObject * boundary_geom_object_pt(const unsigned &b)
Return the geometric object associated with the b-th boundary or null if the boundary has associated ...
double region_attribute(const unsigned &i)
Return the attribute associated with region i.
FiniteElement * boundary_element_in_region_pt(const unsigned &b, const unsigned &r, const unsigned &e) const
Return pointer to the e-th element adjacent to boundary b in region r.
std::map< unsigned, Vector< double > > & boundary_final_coordinate()
Return direct access to the final coordinates of a boundary.
unsigned nboundary_segment(const unsigned &b)
Return the number of segments associated with a boundary.
std::map< unsigned, Vector< Vector< double > > > & boundary_segment_final_coordinate()
Return direct access to the final coordinates for the segments that are part of a boundary.
unsigned long nboundary_segment_node(const unsigned &b)
Return the number of segments associated with a boundary.
std::map< unsigned, Vector< Vector< double > > > & boundary_segment_initial_coordinate()
Return direct access to the initial coordinates for the segments that are part of a boundary.
int face_index_at_boundary_in_region(const unsigned &b, const unsigned &r, const unsigned &e) const
Return face index of the e-th element adjacent to boundary b in region r.
std::map< unsigned, Vector< double > > & boundary_initial_coordinate()
Return direct access to the initial coordinates of a boundary.
unsigned nboundary_element_in_region(const unsigned &b, const unsigned &r) const
Return the number of elements adjacent to boundary b in region r.
unsigned nregion()
Return the number of regions specified by attributes.
std::map< unsigned, Vector< double > > & boundary_segment_final_zeta()
Return direct access to the final zeta for the segments that are part of a boundary.
std::map< unsigned, Vector< double > > & boundary_segment_initial_arclength()
Return direct access to the initial arclength for the segments that are part of a boundary.
FiniteElement * region_element_pt(const unsigned &i, const unsigned &e)
Return the e-th element in the i-th region.
std::map< unsigned, Vector< double > > & boundary_initial_zeta_coordinate()
Return direct access to the initial zeta coordinate of a boundary.
unsigned nregion_element(const unsigned &i)
Return the number of elements in the i-th region.
std::map< unsigned, Vector< double > > & boundary_coordinate_limits()
Return access to the vector of boundary coordinates associated with each geometric object.
std::map< unsigned, Vector< double > > & boundary_final_zeta_coordinate()
Return direct access to the final zeta coordinates of a boundary.
A slight extension to the standard template vector class so that we can include "graceful" array rang...
std::string string(const unsigned &i)
Return the i-th string or "" if the relevant string hasn't been defined.
bool Doc_comprehensive_timings
Global boolean to switch on comprehensive timing – can probably be declared const false when developm...
void get_required_nodal_information_helper(int &iproc, Node *nod_pt, Mesh *const &mesh_pt, int &n_cont_inter_values, Vector< unsigned > &send_unsigneds, Vector< double > &send_doubles)
Helper function to get the required nodal information from an external haloed node so that a fully-fu...
Vector< std::string > Flat_packed_unsigneds_string
unsigned Counter_for_flat_packed_unsigneds
Counter used when processing vector of flat-packed unsigneds – this is really "private" data,...
Vector< double > Flat_packed_doubles
Vector of flat-packed doubles to be communicated with other processors.
Vector< unsigned > Flat_packed_unsigneds
Vector of flat-packed unsigneds to be communicated with other processors – this is really "private" d...
bool Doc_timings
Boolean to indicate whether to doc timings or not.
bool Doc_stats
Boolean to indicate whether to output basic info during setup_multi_domain_interaction() routines.
bool Doc_full_stats
Boolean to indicate whether to output further info during setup_multi_domain_interaction() routines.
unsigned Counter_for_flat_packed_doubles
Counter used when processing vector of flat-packed doubles – this is really "private" data,...
double timer()
returns the time in seconds after some point in past
double Tolerable_error
Acceptable discrepancy for mismatch in vertex coordinates. In paranoid mode, the code will die if the...
void initialise_triangulateio(TriangulateIO &triangle_io)
Initialise TriangulateIO structure.
void clear_triangulateio(TriangulateIO &triangulate_io, const bool &clear_hole_data)
Clear TriangulateIO structure.
TriangulateIO deep_copy_of_triangulateio_representation(TriangulateIO &triangle_io, const bool &quiet)
Make (partial) deep copy of TriangulateIO object. We only copy those items we need within oomph-lib's...
//////////////////////////////////////////////////////////////////// ////////////////////////////////...
frac
A class for all elements that solve the Advection Diffusion equations using isoparametric elements.
x
Pseudo buckling ring: Circular ring deformed by the N-th buckling mode of a thin-wall elastic ring.
u
Z2-error-estimator: Elements that can be used with Z2 error estimation should be derived from the bas...
struct oomph::classcomp Bottom_left_sorter
int f(x_0, x_1...)\ dx_0 \ dx_1...
Generic class for numerical integration schemes:
OomphInfo oomph_info
Single (global) instantiation of the OomphInfo object – this is used throughout the library as a "rep...
The Triangle data structure, modified from the triangle.h header supplied with triangle 1....
double * pointlist
Pointer to list of points x coordinate followed by y coordinate.
int numberoftriangleattributes
int * pointmarkerlist
Pointer to list of point markers.
double * trianglearealist
double * triangleattributelist
double * pointattributelist
Pointer to list of point attributes.
int numberofpointattributes
bool operator()(const std::pair< double, double > &lhs, const std::pair< double, double > &rhs) const